
#include <BFile>
#include "member_BObcDocument.h"

using namespace BWE;

#define RegistObjectSign(type, sign) regist(B##type::TypeName(), sign, (readFunc)&member_BObcDocument::read##type, (writeFunc)&member_BObcDocument::write##type)

member_BObcDocument::member_BObcDocument(BObcDocument* obcDocument)
{
	boss = obcDocument;
	stream = 0;
	chunkLevel = 0;
	if (signTypeMap.empty())
	{
		RegistObjectSign(Object, SIGN_OBJECT);
		RegistObjectSign(Scene, SIGN_SCENE);
		RegistObjectSign(Group, SIGN_GROUP);
		RegistObjectSign(Node, SIGN_NODE);
		RegistObjectSign(Light, SIGN_LIGHT);
		RegistObjectSign(Camera, SIGN_CAMERA);
		RegistObjectSign(Body, SIGN_BODY);
		RegistObjectSign(SoftBody, SIGN_SOFTBODY);

		RegistObjectSign(Shape, SIGN_SHAPE);
		RegistObjectSign(Mesh, SIGN_MESH);
		RegistObjectSign(Geometry, SIGN_GEOMETRY);
		RegistObjectSign(Textual, SIGN_TEXTUAL);
		RegistObjectSign(Particle, SIGN_PARTICLE);
		RegistObjectSign(Element, SIGN_ELEMENT);

		RegistObjectSign(Cube, SIGN_CUBE);
		RegistObjectSign(Cone, SIGN_CONE);
		RegistObjectSign(Cylinder, SIGN_CYLINDER);
		RegistObjectSign(Sphere, SIGN_SPHERE);
		RegistObjectSign(GeoSphere, SIGN_GEOSPHERE);
		RegistObjectSign(Tube, SIGN_TUBE);
		RegistObjectSign(Torus, SIGN_TORUS);
		RegistObjectSign(Surface, SIGN_SURFACE);
		RegistObjectSign(Terrain, SIGN_TERRAIN);
		RegistObjectSign(Billboard, SIGN_BILLBOARD);
		RegistObjectSign(Particle, SIGN_PARTICLE);
		RegistObjectSign(Capsule, SIGN_CAPSULE);
		RegistObjectSign(LineStripe, SIGN_LINESTRIPE);
		RegistObjectSign(SplineCurve, SIGN_SPLINECURVE);

		RegistObjectSign(Restraint, SIGN_RESTRAINT);
		RegistObjectSign(PointRestraint, SIGN_POINT_RESTRAINT);
		RegistObjectSign(HingeRestraint, SIGN_HINGE_RESTRAINT);
		RegistObjectSign(SliderRestraint, SIGN_SLIDER_RESTRAINT);
		RegistObjectSign(ConearRestraint, SIGN_CONEAR_RESTRAINT);
		RegistObjectSign(SixdofRestraint, SIGN_SIXDOF_RESTRAINT);
		RegistObjectSign(FixedRestraint, SIGN_FIXED_RESTRAINT);
		RegistObjectSign(GearRestraint, SIGN_GEAR_RESTRAINT);

		RegistObjectSign(Material, SIGN_MATERIAL);
		RegistObjectSign(Texture, SIGN_TEXTURE);
		RegistObjectSign(Image, SIGN_IMAGE);
		RegistObjectSign(Pixmap, SIGN_PIXMAP);
		RegistObjectSign(Program, SIGN_PROGRAM);
		RegistObjectSign(Uniform, SIGN_UNIFORM);
		RegistObjectSign(Script, SIGN_SCRIPT);
		RegistObjectSign(Source, SIGN_SOURCE);
		RegistObjectSign(SonNode, SIGN_SONNODE);
		RegistObjectSign(XmlNode, SIGN_XMLNODE);

	}
}
member_BObcDocument::~member_BObcDocument()
{

}

void member_BObcDocument::clear()
{
	buffer.clear();
	chunkLevel = 0;
	chunkStack.clear();
	readObjectMap.clear();
	writeObjectMap.clear();
}

BObject* member_BObcDocument::read(const Chunk& chunk)
{
	if (chunk.sign < 200)
		return 0;

	BObject* object = boss->create(chunk.sign);
	if (!object)
		return 0;

	int id = 0;
	Chunk head;
	if (readBeginChunk(head, chunk.end))
	{
		if (head.sign == SIGN_ID)
			stream->read(id);
		else
			stream->move(-6);
	}
	if (id > 0)
	{
		BObject* object = readObjectMap(id);
		if (object)
			return object;
	}

	BArray<member_BObcDocument::readFunc> readFuncs;
	BArray<BObcDocument::readChunk> readChunks;
	for (int i = 0; i < object->typeCount(); i++)
	{
		const char* type = object->typeName(i);
		if (member_BObcDocument::readFunc read = readFuncMap(type))
			readFuncs.append(read);
		if (BObcDocument::readChunk read = readChunkMap(type))
			readChunks.append(read);
	}

	Chunk sub;
	while (readBeginChunk(sub, chunk.end))
	{
		bool result = false;
		while (member_BObcDocument::readFunc read = readFuncs.first())
		{
			if ((this->*read)(sub, object))
			{
				result = true;
				break;
			}
			readFuncs.remove(0);
		}
		if (!result && readChunks.size())
		{
			while (BObcDocument::readChunk read = readChunks.first())
			{
				if ((boss->*read)(*stream, sub.sign, object))
				{
					result = true;
					break;
				}
				readChunks.remove(0);
			}
		}
		if (!result)
		{
			message() << "OBC Error : [" << signTypeMap(chunk.sign) << "] invalid sub chunk " << signTypeMap(sub.sign) << '[' << sub.sign << "]\n";
		}
		readEndChunk(sub);
	}
	if (id > 0)
	{
		readObjectMap[id] = object;
	}
	return object;
}
bool member_BObcDocument::write(const BObject* object)
{
	BUShort sign = SIGN_NONE;
	BArray<member_BObcDocument::writeFunc> writeFuncs;
	BArray<BObcDocument::writeChunk> writeChunks;
	for (int i = 0; i < object->typeCount(); i++)
	{
		const char* typeName = object->typeName(i);
		if (member_BObcDocument::writeFunc write = writeFuncMap(typeName))
		{
			writeFuncs.append(write);
			sign = typeSignMap(typeName);
		}
		if (BObcDocument::writeChunk write = writeChunkMap(typeName))
		{
			writeChunks.append(write);
			sign = typeSignMap(typeName);
		}
	}
	if (writeFuncs.empty())
	{
		message() << "OBC Error : Write object failed : No read func for " << object->className();
		return false;
	}
	int id = writeObjectMap(object);
	if (id == 0 && object->ref_count() > 1)
	{
		id = writeObjectMap.size() + 1;
		writeObjectMap.insert(object, id);
	}
	AutoChunk chunk(this, sign);
	if (id > 0)
	{
		AutoChunk idchunk(this, SIGN_ID);
		stream->write(id);
	}
	for (int i = 0; i < writeFuncs.size(); i++)
	{
		member_BObcDocument::writeFunc write = writeFuncs[i];
		if (!(this->*write)(object))
		{
			message() << "OBC Error : Write object failed " << object->className();
			return false;
		}
	}
	for (int i = 0; i < writeChunks.size(); i++)
	{
		BObcDocument::writeChunk write = writeChunks[i];
		if (!(boss->*write)(*stream, object))
		{
			message() << "OBC Error : Write object failed " << object->className();
			return false;
		}
	}
	return true;
}

void member_BObcDocument::beginChunk(BUShort sign)
{
#ifdef REAL_IS_DOUBLE
	if (sign < 100)
		sign += 100;
#endif
	ChunkInfo& cinfo = chunkStack.push();
	cinfo.sign = sign;
	cinfo.end = 0;
	cinfo.begin = stream->offset();
	stream->write(cinfo.sign);
	stream->write(cinfo.end);
	chunkLevel++;
}
void member_BObcDocument::endChunk(BUShort sign)
{
#ifdef REAL_IS_DOUBLE
	if (sign < 100)
		sign += 100;
#endif
	ChunkInfo& cinfo = chunkStack.last();
	cinfo.end = stream->offset();
	stream->seek(cinfo.begin);
	stream->write(cinfo.sign);
	stream->write(cinfo.end);
	stream->seek(cinfo.end);
	chunkLevel--;
	chunkStack.pop();
}

bool member_BObcDocument::readBeginChunk(Chunk& chunk, int end)
{
	if (stream->offset() >= end)
		return false;
	if (!stream->read(chunk))
		return false;
	chunkLevel++;
	return true;
}
bool member_BObcDocument::readEndChunk(Chunk& chunk)
{
	chunkLevel--;
	if (!stream->seek(chunk.end))
	{
		static BString text;
		text.reset();
		text.append('\t', chunkLevel);
		text << signTypeMap(chunk.sign) << "end faild";
		return false;
	}
	return true;
}

BString& member_BObcDocument::message()
{
	if (messageValue.empty())
		messageValue = new BString();
	BString& text = messageValue;
	return text;
}
const BString& member_BObcDocument::message() const
{
	const BString& text = messageValue;
	return text;
}

bool member_BObcDocument::readObject(const Chunk& chunk, BObject* object)
{
	if (chunk.sign == SIGN_NAME)
	{
		BString name;
		stream->read(name);
		object->setName(name);
		return true;
	}
	if (chunk.sign == SIGN_ENABLED)
	{
		bool enabled = false;
		stream->read(enabled);
		object->setEnabled(enabled);
		return true;
	}
	return false;
}
bool member_BObcDocument::readScene(const Chunk& chunk, BScene* scene)
{
	if (chunk.sign == SIGN_OPTIMIZED)
	{
		bool optimized = false;
		stream->read(optimized);
		return true;
	}
	BObjectHolder object = this->read(chunk);
	if (BShape* shape = object.as<BShape>())
		return scene->insert(shape);
	else if (BNode* node = object.as<BNode>())
		return scene->insert(node);
	else if (BRestraint* restraint = object.as<BRestraint>())
		return scene->insert(restraint);
	else if (BGroup* group = object.as<BGroup>())
		return scene->insert(group);
	return false;
}
bool member_BObcDocument::readGroup(const Chunk& chunk, BGroup* group)
{
	if (chunk.sign == SIGN_VISIBLE)
	{
		bool visible = true;
		stream->read(visible);
		group->setVisible(visible);
		return true;
	}
	BObjectHolder object = this->read(chunk);
	if (object.empty())
		return false;
	if (BShape* shape = object.as<BShape>())
		return group->insert(shape);
	else if (BNode* node = object.as<BNode>())
		return group->insert(node);
	else if (BGroup* childGroup = object.as<BGroup>())
		return group->insert(childGroup);
	else if (BRestraint* restraint = object.as<BRestraint>())
		return group->insert(restraint);
	return false;
}
bool member_BObcDocument::readNode(const Chunk& chunk, BNode* node)
{
	if (chunk.sign == SIGN_VISIBLE)
	{
		bool visible = true;
		stream->read(visible);
		node->setVisible(visible);
		return true;
	}
	if (chunk.sign == SIGN_OPTIMIZED)
	{
		bool optimized = false;
		stream->read(optimized);
		node->setOptimized(optimized);
		return true;
	}
	if (chunk.sign == SIGN_MATRIX)
	{
		BMatrixf matrix;
		stream->read(matrix);
		node->setMatrix(matrix);
		return true;
	}
	if (chunk.sign == SIGN_MATRIX_D)
	{
		BMatrixd matrix;
		stream->read(matrix);
		node->setMatrix(matrix);
		return true;
	}
	BHolder<BObject> object = this->read(chunk);
	if (BShape* shape = object.as<BShape>())
		return node->insertShape(shape);
	return false;
}
bool member_BObcDocument::readLight(const Chunk& chunk, BLight* light)
{
	switch (chunk.sign)
	{
	case SIGN_AMBIENT:
	{
		BColor ambient;
		stream->read(ambient);
		light->setAmbient(ambient);
		break;
	}
	case SIGN_DIFFUSE:
	{
		BColor diffuse;
		stream->read(diffuse);
		light->setDiffuse(diffuse);
		break;
	}
	case SIGN_SPECULAR:
	{
		BColor specular;
		stream->read(specular);
		light->setSpecular(specular);
		break;
	}
	case SIGN_ATTENUATION:
	{
		float attenuation = 0.0f;
		stream->read(attenuation);
		light->setAttenuation(attenuation);
		break;
	}
	case SIGN_ATTENUATION2:
	{
		float attenuation2 = 0.0f;
		stream->read(attenuation2);
		light->setAttenuation2(attenuation2);
		break;
	}
	case SIGN_CUTOFF:
	{
		float cutoff = 0.0f;
		stream->read(cutoff);
		light->setCutoff(cutoff);
		break;
	}
	case SIGN_EXPONENT:
	{
		float exponent = 0.0f;
		stream->read(exponent);
		light->setExponent(exponent);
		break;
	}
	case SIGN_RADIUS:
	{
		float radius = 0;
		stream->read(radius);
		light->setRadius(radius);
		break;
	}
	case SIGN_RADIUS_D:
	{
		double radius = 0;
		stream->read(radius);
		light->setRadius(radius);
		break;
	}
	default:
		return false;
	}
	return true;
}
bool member_BObcDocument::readCamera(const Chunk& chunk, BCamera* camera)
{
	switch (chunk.sign)
	{
	case SIGN_ORTHO:
	{
		bool ortho;
		stream->read(ortho);
		camera->setOrtho(ortho);
		break;
	}
	case SIGN_CENTER:
	{
		BVectorf center;
		stream->read(center);
		camera->setCenter(center);
		break;
	}
	case SIGN_CENTER_D:
	{
		BVectord center;
		stream->read(center);
		camera->setCenter(center);
		break;
	}
	case SIGN_UP:
	{
		BVectorf up;
		stream->read(up);
		camera->setUp(up);
		break;
	}
	case SIGN_UP_D:
	{
		BVectord up;
		stream->read(up);
		camera->setUp(up);
		break;
	}
	case SIGN_NEAR:
	{
		float near;
		stream->read(near);
		break;
	}
	case SIGN_NEAR_D:
	{
		double near;
		stream->read(near);
		break;
	}
	case SIGN_FAR:
	{
		float far;
		stream->read(far);
		camera->setFar(far);
		break;
	}
	case SIGN_FAR_D:
	{
		double far;
		stream->read(far);
		camera->setFar((BReal)far);
		break;
	}
	case SIGN_FOVY:
	{
		float fovy;
		stream->read(fovy);
		camera->setFovy(fovy);
		break;
	}
	case SIGN_FOVY_D:
	{
		double fovy;
		stream->read(fovy);
		camera->setFovy((BReal)fovy);
		break;
	}
	case SIGN_LENSSIZE:
	{
		float lensWidth, lensHeight;
		stream->read(lensWidth);
		stream->read(lensHeight);
		camera->setLensWidth(lensWidth);
		camera->setLensHeight(lensHeight);
		break;
	}
	case SIGN_LENSSIZE_D:
	{
		double lensWidth, lensHeight;
		stream->read(lensWidth);
		stream->read(lensHeight);
		camera->setLensWidth((BReal)lensWidth);
		camera->setLensHeight((BReal)lensHeight);
		break;
	}
	case SIGN_PIXELSIZE:
	{
		int pixelWidth, pixelHeight;
		stream->read(pixelWidth);
		stream->read(pixelHeight);
		camera->setPixelSize(pixelWidth, pixelHeight);
		break;
	}
	case SIGN_PIXELPOLICY:
	{
		Policy pixelPolicy;
		stream->read(pixelPolicy);
		camera->setPixelSizePolicy(pixelPolicy);
		break;
	}
	case SIGN_BACKGROUND:
	{
		BColor color;
		stream->read(color);
		camera->setColor(color);
		break;
	}
	default:
		return false;
	}
	return true;
}
bool member_BObcDocument::readBody(const Chunk& chunk, BBody* body)
{
	switch (chunk.sign)
	{
	case SIGN_DEACTIME:
	{
		float deactime = 0;
		stream->read(deactime);
		body->setDeactivatedTime((BReal)deactime);
		break;
	}
	case SIGN_DEACTIME_D:
	{
		double deactime = 0;
		stream->read(deactime);
		body->setDeactivatedTime((BReal)deactime);
		break;
	}
	case SIGN_MASS:
	{
		float mass;
		stream->read(mass);
		body->setMass((BReal)mass);
		break;
	}
	case SIGN_MASS_D:
	{
		double mass;
		stream->read(mass);
		body->setMass((BReal)mass);
		break;
	}
	case SIGN_FRICTION:
	{
		float friction = 0;
		float rollingFriction = 0;
		stream->read(friction);
		stream->read(rollingFriction);
		body->setFriction((BReal)friction);
		body->setRollingFriction((BReal)rollingFriction);
		break;
	}
	case SIGN_FRICTION_D:
	{
		double friction = 0;
		double rollingFriction = 0;
		stream->read(friction);
		stream->read(rollingFriction);
		body->setFriction((BReal)friction);
		body->setRollingFriction((BReal)rollingFriction);
		break;
	}
	case SIGN_RESTITUTION:
	{
		float restitution = 0;
		stream->read(restitution);
		body->setRestitution((BReal)restitution);
		break;
	}
	case SIGN_RESTITUTION_D:
	{
		double restitution = 0;
		stream->read(restitution);
		body->setRestitution((BReal)restitution);
		break;
	}
	case SIGN_INERTIA:
	{
		BVectorf inertia;
		stream->read(inertia);
		body->setInertia(inertia);
		break;
	}
	case SIGN_INERTIA_D:
	{
		BVectord inertia;
		stream->read(inertia);
		body->setInertia(inertia);
		break;
	}
	case SIGN_FORCE:
	{
		BVectorf force;
		stream->read(force);
		body->setForce(force);
		break;
	}
	case SIGN_FORCE_D:
	{
		BVectord force;
		stream->read(force);
		body->setForce(force);
		break;
	}
	case SIGN_GRAVITY:
	{
		BVectorf gravity;
		stream->read(gravity);
		body->setGravity(gravity);
		break;
	}
	case SIGN_GRAVITY_D:
	{
		BVectord gravity;
		stream->read(gravity);
		body->setGravity(gravity);
		break;
	}
	case SIGN_LINEAR_THRESHOLD:
	{
		float linearThreshold = 0;
		stream->read(linearThreshold);
		body->setLinearThreshold((BReal)linearThreshold);
		break;
	}
	case SIGN_LINEAR_THRESHOLD_D:
	{
		double linearThreshold = 0;
		stream->read(linearThreshold);
		body->setLinearThreshold((BReal)linearThreshold);
		break;
	}
	case SIGN_ANGULAR_THRESHOLD:
	{
		float angularThreshold = 0;
		stream->read(angularThreshold);
		body->setAngularThreshold((BReal)angularThreshold);
		break;
	}
	case SIGN_ANGULAR_THRESHOLD_D:
	{
		double angularThreshold = 0;
		stream->read(angularThreshold);
		body->setAngularThreshold((BReal)angularThreshold);
		break;
	}
	case SIGN_LINEAR_VELOCITY:
	{
		BVectorf linearVelocity;
		stream->read(linearVelocity);
		body->setLinearVelocity(linearVelocity);
		break;
	}
	case SIGN_LINEAR_VELOCITY_D:
	{
		BVectord linearVelocity;
		stream->read(linearVelocity);
		body->setLinearVelocity(linearVelocity);
		break;
	}
	case SIGN_ANGULAR_VELOCITY:
	{
		BVectorf angularVelocity;
		stream->read(angularVelocity);
		body->setAngularVelocity(angularVelocity);
		break;
	}
	case SIGN_ANGULAR_VELOCITY_D:
	{
		BVectord angularVelocity;
		stream->read(angularVelocity);
		body->setAngularVelocity(angularVelocity);
		break;
	}
	default:
		return false;
	}
	return true;
}
bool member_BObcDocument::readSoftBody(const Chunk& chunk, BSoftBody* softBody)
{
	return false;
}

bool member_BObcDocument::readRestraint(const Chunk& chunk, BRestraint* restraint)
{
	switch (chunk.sign)
	{
	case SIGN_NODEA_ID:
	{
		int idA = 0;
		stream->read(idA);
		BBody* bodyA = dynamic_cast<BBody*>(readObjectMap[idA]);
		restraint->setBodyA(bodyA);
		break;
	}
	case SIGN_NODEB_ID:
	{
		int idB = 0;
		stream->read(idB);
		BBody* bodyB = dynamic_cast<BBody*>(readObjectMap[idB]);
		restraint->setBodyB(bodyB);
		break;
	}
	case SIGN_PIVOTA:
	{
		BVectorf pivotA;
		stream->read(pivotA);
		restraint->setPivotA(pivotA);
		break;
	}
	case SIGN_PIVOTA_D:
	{
		BVectord pivotA;
		stream->read(pivotA);
		restraint->setPivotA(pivotA);
		break;
	}
	case SIGN_PIVOTB:
	{
		BVectorf pivotB;
		stream->read(pivotB);
		restraint->setPivotB(pivotB);
		break;
	}
	case SIGN_PIVOTB_D:
	{
		BVectord pivotB;
		stream->read(pivotB);
		restraint->setPivotB(pivotB);
		break;
	}
	case SIGN_COLLIDING:
	{
		bool colliding = false;
		stream->read(colliding);
		restraint->setColliding(colliding);
		break;
	}
	case SIGN_BREAK_IMPULSE:
	{
		float breakImpulse = 0;
		stream->read(breakImpulse);
		restraint->setBreakImpulse(breakImpulse);
		break;
	}
	case SIGN_BREAK_IMPULSE_D:
	{
		double breakImpulse = 0;
		stream->read(breakImpulse);
		restraint->setBreakImpulse((BReal)breakImpulse);
		break;
	}
	default:
		return false;
	}
	return true;
}
bool member_BObcDocument::readPointRestraint(const Chunk& chunk, BPointRestraint* restraint)
{
	switch (chunk.sign)
	{
	case SIGN_DAMPING:
	{
		float damping = 0;
		stream->read(damping);
		restraint->setDamping(BReal(damping));
		break;
	}
	case SIGN_DAMPING_D:
	{
		double damping = 0;
		stream->read(damping);
		restraint->setDamping(BReal(damping));
		break;
	}
	case SIGN_IMPULSE_LIMIT:
	{
		float setImpulseLimit = 0;
		stream->read(setImpulseLimit);
		restraint->setImpulseLimit(BReal(setImpulseLimit));
		break;
	}
	case SIGN_IMPULSE_LIMIT_D:
	{
		double setImpulseLimit = 0;
		stream->read(setImpulseLimit);
		restraint->setImpulseLimit(BReal(setImpulseLimit));
		break;
	}
	default:
		return false;
	}
	return true;
}
bool member_BObcDocument::readHingeRestraint(const Chunk& chunk, BHingeRestraint* hingeRestraint)
{
	switch (chunk.sign)
	{
	case SIGN_AXISA:
	{
		BVectorf axisA;
		stream->read(axisA);
		hingeRestraint->setAxisA(axisA);
		break;
	}
	case SIGN_AXISA_D:
	{
		BVectord axisA;
		stream->read(axisA);
		hingeRestraint->setAxisA(axisA);
		break;
	}
	case SIGN_AXISB:
	{
		BVectorf axisB;
		stream->read(axisB);
		hingeRestraint->setAxisB(axisB);
		break;
	}
	case SIGN_AXISB_D:
	{
		BVectord axisB;
		stream->read(axisB);
		hingeRestraint->setAxisB(axisB);
		break;
	}
	case SIGN_ANGULAR_LIMIT:
	{
		BRangef angleRange;
		stream->read(angleRange);
		hingeRestraint->setAngularLimit(angleRange);
		break;
	}
	case SIGN_ANGULAR_LIMIT_D:
	{
		BRanged angleRange;
		stream->read(angleRange);
		hingeRestraint->setAngularLimit(angleRange);
		break;
	}
	case SIGN_MOTOR_ENABLED:
	{
		bool enabled = false;
		stream->read(enabled);
		hingeRestraint->setMotorEnabled(enabled);
		break;
	}
	case SIGN_MOTOR_TARGET:
	{
		float target;
		stream->read(target);
		hingeRestraint->setMotorTarget((BReal)target);
		break;
	}
	case SIGN_MOTOR_TARGET_D:
	{
		double target;
		stream->read(target);
		hingeRestraint->setMotorTarget((BReal)target);
		break;
	}
	case SIGN_MOTOR_VELOCITY:
	{
		float velocity;
		stream->read(velocity);
		hingeRestraint->setMotorVelocity((BReal)velocity);
		break;
	}
	case SIGN_MOTOR_VELOCITY_D:
	{
		double velocity;
		stream->read(velocity);
		hingeRestraint->setMotorVelocity((BReal)velocity);
		break;
	}
	case SIGN_MOTOR_MAXFORCE:
	{
		float motorMaxForce;
		stream->read(motorMaxForce);
		hingeRestraint->setMotorMaxForce((BReal)motorMaxForce);
		break;
	}
	case SIGN_MOTOR_MAXFORCE_D:
	{
		double motorMaxForce;
		stream->read(motorMaxForce);
		hingeRestraint->setMotorMaxForce((BReal)motorMaxForce);
		break;
	}
	default:
		return false;
	}
	return true;
}
bool member_BObcDocument::readSliderRestraint(const Chunk& chunk, BSliderRestraint* sliderRestraint)
{
	switch (chunk.sign)
	{
	case SIGN_AXISA:
	{
		BVectorf axisA;
		stream->read(axisA);
		sliderRestraint->setAxisA(axisA);
		break;
	}
	case SIGN_AXISA_D:
	{
		BVectord axisA;
		stream->read(axisA);
		sliderRestraint->setAxisA(axisA);
		break;
	}
	case SIGN_AXISB:
	{
		BVectorf axisB;
		stream->read(axisB);
		sliderRestraint->setAxisB(axisB);
		break;
	}
	case SIGN_AXISB_D:
	{
		BVectord axisB;
		stream->read(axisB);
		sliderRestraint->setAxisB(axisB);
		break;
	}
	case SIGN_LINEAR_LIMIT:
	{
		BRangef linearLimit;
		stream->read(linearLimit);
		sliderRestraint->setLinearLimit(linearLimit);
		break;
	}
	case SIGN_LINEAR_LIMIT_D:
	{
		BRanged linearLimit;
		stream->read(linearLimit);
		sliderRestraint->setLinearLimit(linearLimit);
		break;
	}
	case SIGN_ANGULAR_LIMIT:
	{
		BRangef angularLimit;
		stream->read(angularLimit);
		sliderRestraint->setAngularLimit(angularLimit);
		break;
	}
	case SIGN_ANGULAR_LIMIT_D:
	{
		BRanged angularLimit;
		stream->read(angularLimit);
		sliderRestraint->setAngularLimit(angularLimit);
		break;
	}
	case SIGN_LINEAR_MOTOR_ENABLED:
	{
		bool enabled = false;
		stream->read(enabled);
		sliderRestraint->setLinearMotorEnabled(enabled);
		break;
	}
	case SIGN_LINEAR_MOTOR_TARGET:
	{
		float target;
		stream->read(target);
		sliderRestraint->setLinearMotorTarget((BReal)target);
		break;
	}
	case SIGN_LINEAR_MOTOR_TARGET_D:
	{
		double target;
		stream->read(target);
		sliderRestraint->setLinearMotorTarget((BReal)target);
		break;
	}
	case SIGN_LINEAR_MOTOR_VELOCITY:
	{
		float velocity;
		stream->read(velocity);
		sliderRestraint->setLinearMotorVelocity((BReal)velocity);
		break;
	}
	case SIGN_LINEAR_MOTOR_VELOCITY_D:
	{
		double velocity;
		stream->read(velocity);
		sliderRestraint->setLinearMotorVelocity((BReal)velocity);
		break;
	}
	case SIGN_LINEAR_MOTOR_MAXFORCE:
	{
		float maxImpulse;
		stream->read(maxImpulse);
		sliderRestraint->setLinearMotorMaxForce((BReal)maxImpulse);
		break;
	}
	case SIGN_LINEAR_MOTOR_MAXFORCE_D:
	{
		double maxImpulse;
		stream->read(maxImpulse);
		sliderRestraint->setLinearMotorMaxForce((BReal)maxImpulse);
		break;
	}
	case SIGN_ANGULAR_MOTOR_ENABLED:
	{
		bool enabled = false;
		stream->read(enabled);
		sliderRestraint->setAngularMotorEnabled(enabled);
		break;
	}
	case SIGN_ANGULAR_MOTOR_TARGET:
	{
		float target;
		stream->read(target);
		sliderRestraint->setAngularMotorTarget((BReal)target);
		break;
	}
	case SIGN_ANGULAR_MOTOR_TARGET_D:
	{
		double target;
		stream->read(target);
		sliderRestraint->setAngularMotorTarget((BReal)target);
		break;
	}
	case SIGN_ANGULAR_MOTOR_VELOCITY:
	{
		float velocity;
		stream->read(velocity);
		sliderRestraint->setAngularMotorVelocity((BReal)velocity);
		break;
	}
	case SIGN_ANGULAR_MOTOR_VELOCITY_D:
	{
		double velocity;
		stream->read(velocity);
		sliderRestraint->setAngularMotorVelocity((BReal)velocity);
		break;
	}
	case SIGN_ANGULAR_MOTOR_MAXFORCE:
	{
		float maxImpulse;
		stream->read(maxImpulse);
		sliderRestraint->setAngularMotorMaxForce((BReal)maxImpulse);
		break;
	}
	case SIGN_ANGULAR_MOTOR_MAXFORCE_D:
	{
		double maxImpulse;
		stream->read(maxImpulse);
		sliderRestraint->setAngularMotorMaxForce((BReal)maxImpulse);
		break;
	}
	default:
		BHolder<BObject> object = this->read(chunk);
		if (BLineStripe* stripe = object.as<BLineStripe>())
		{
			sliderRestraint->setStripe(stripe);
			break;
		}
		if (BSplineCurve* curve = object.as<BSplineCurve>())
		{
			sliderRestraint->setCurve(curve);
			break;
		}
		return false;
	}
	return true;
}
bool member_BObcDocument::readConearRestraint(const Chunk& chunk, BConearRestraint* conearRestraint)
{
	switch (chunk.sign)
	{
	case SIGN_DAMPING:
	{
		float damping;
		stream->read(damping);
		conearRestraint->setDamping(BReal(damping));
		break;
	}
	case SIGN_DAMPING_D:
	{
		double damping;
		stream->read(damping);
		conearRestraint->setDamping(BReal(damping));
		break;
	}
	case SIGN_AXISA:
	{
		BVectorf swingAxis;
		stream->read(swingAxis);
		conearRestraint->setAxisA(swingAxis);
		break;
	}
	case SIGN_AXISA_D:
	{
		BVectord swingAxis;
		stream->read(swingAxis);
		conearRestraint->setAxisA(swingAxis);
		break;
	}
	case SIGN_AXISB:
	{
		BVectorf twinstAxis;
		stream->read(twinstAxis);
		conearRestraint->setAxisB(twinstAxis);
		break;
	}
	case SIGN_AXISB_D:
	{
		BVectord twinstAxis;
		stream->read(twinstAxis);
		conearRestraint->setAxisB(twinstAxis);
		break;
	}
	default:
		return false;
	}
	return true;
}
bool member_BObcDocument::readSixdofRestraint(const Chunk& chunk, BSixdofRestraint* sixdofRestraint)
{
	switch (chunk.sign)
	{
	case SIGN_LINEAR_LIMIT:
	{
		BVectorf lowerLimit;
		BVectorf upperLimit;
		stream->read(lowerLimit);
		stream->read(upperLimit);
		sixdofRestraint->setLinearLowerLimit(lowerLimit);
		sixdofRestraint->setLinearUpperLimit(upperLimit);
		break;
	}
	case SIGN_LINEAR_LIMIT_D:
	{
		BVectord lowerLimit;
		BVectord upperLimit;
		stream->read(lowerLimit);
		stream->read(upperLimit);
		sixdofRestraint->setLinearLowerLimit(lowerLimit);
		sixdofRestraint->setLinearUpperLimit(upperLimit);
		break;
	}
	case SIGN_ANGULAR_LIMIT:
	{
		BVectorf lowerLimit;
		BVectorf upperLimit;
		stream->read(lowerLimit);
		stream->read(upperLimit);
		sixdofRestraint->setAngularLowerLimit(lowerLimit);
		sixdofRestraint->setAngularUpperLimit(upperLimit);
		break;
	}
	case SIGN_ANGULAR_LIMIT_D:
	{
		BVectord lowerLimit;
		BVectord upperLimit;
		stream->read(lowerLimit);
		stream->read(upperLimit);
		sixdofRestraint->setAngularLowerLimit(lowerLimit);
		sixdofRestraint->setAngularUpperLimit(upperLimit);
		break;
	}
	case SIGN_MOTOR_ENABLED:
	{
		bool linearMotorXEnabled = false;
		bool linearMotorYEnabled = false;
		bool linearMotorZEnabled = false;
		stream->read(linearMotorXEnabled);
		stream->read(linearMotorYEnabled);
		stream->read(linearMotorZEnabled);
		sixdofRestraint->setLinearMotorEnabled(0, linearMotorXEnabled);
		sixdofRestraint->setLinearMotorEnabled(1, linearMotorYEnabled);
		sixdofRestraint->setLinearMotorEnabled(2, linearMotorZEnabled);

		bool angularMotorXEnabled = false;
		bool angularMotorYEnabled = false;
		bool angularMotorZEnabled = false;
		stream->read(angularMotorXEnabled);
		stream->read(angularMotorYEnabled);
		stream->read(angularMotorZEnabled);
		sixdofRestraint->setAngularMotorEnabled(0, angularMotorXEnabled);
		sixdofRestraint->setAngularMotorEnabled(1, angularMotorYEnabled);
		sixdofRestraint->setAngularMotorEnabled(2, angularMotorZEnabled);
		break;
	}
	case SIGN_MOTOR_TARGET:
	{
		float linearMotorXTarget = 0;
		float linearMotorYTarget = 0;
		float linearMotorZTarget = 0;
		stream->read(linearMotorXTarget);
		stream->read(linearMotorYTarget);
		stream->read(linearMotorZTarget);
		sixdofRestraint->setLinearMotorTarget(0, (BReal)linearMotorXTarget);
		sixdofRestraint->setLinearMotorTarget(1, (BReal)linearMotorYTarget);
		sixdofRestraint->setLinearMotorTarget(2, (BReal)linearMotorZTarget);

		float angularMotorXTarget = 0;
		float angularMotorYTarget = 0;
		float angularMotorZTarget = 0;
		stream->read(angularMotorXTarget);
		stream->read(angularMotorYTarget);
		stream->read(angularMotorZTarget);
		sixdofRestraint->setAngularMotorTarget(0, (BReal)angularMotorXTarget);
		sixdofRestraint->setAngularMotorTarget(1, (BReal)angularMotorYTarget);
		sixdofRestraint->setAngularMotorTarget(2, (BReal)angularMotorZTarget);
		break;
	}
	case SIGN_MOTOR_TARGET_D:
	{
		double linearMotorXTarget = 0;
		double linearMotorYTarget = 0;
		double linearMotorZTarget = 0;
		stream->read(linearMotorXTarget);
		stream->read(linearMotorYTarget);
		stream->read(linearMotorZTarget);
		sixdofRestraint->setLinearMotorTarget(0, (BReal)linearMotorXTarget);
		sixdofRestraint->setLinearMotorTarget(1, (BReal)linearMotorYTarget);
		sixdofRestraint->setLinearMotorTarget(2, (BReal)linearMotorZTarget);

		double angularMotorXTarget = 0;
		double angularMotorYTarget = 0;
		double angularMotorZTarget = 0;
		stream->read(angularMotorXTarget);
		stream->read(angularMotorYTarget);
		stream->read(angularMotorZTarget);
		sixdofRestraint->setAngularMotorTarget(0, (BReal)angularMotorXTarget);
		sixdofRestraint->setAngularMotorTarget(1, (BReal)angularMotorYTarget);
		sixdofRestraint->setAngularMotorTarget(2, (BReal)angularMotorZTarget);
		break;
	}
	case SIGN_MOTOR_VELOCITY:
	{
		float linearMotorXVelocity = 0;
		float linearMotorYVelocity = 0;
		float linearMotorZVelocity = 0;
		stream->read(linearMotorXVelocity);
		stream->read(linearMotorYVelocity);
		stream->read(linearMotorZVelocity);
		sixdofRestraint->setLinearMotorVelocity(0, (BReal)linearMotorXVelocity);
		sixdofRestraint->setLinearMotorVelocity(1, (BReal)linearMotorYVelocity);
		sixdofRestraint->setLinearMotorVelocity(2, (BReal)linearMotorZVelocity);

		float angularMotorXVelocity = 0;
		float angularMotorYVelocity = 0;
		float angularMotorZVelocity = 0;
		stream->read(angularMotorXVelocity);
		stream->read(angularMotorYVelocity);
		stream->read(angularMotorZVelocity);
		sixdofRestraint->setAngularMotorVelocity(0, (BReal)angularMotorXVelocity);
		sixdofRestraint->setAngularMotorVelocity(1, (BReal)angularMotorYVelocity);
		sixdofRestraint->setAngularMotorVelocity(2, (BReal)angularMotorZVelocity);
		break;
	}
	case SIGN_MOTOR_VELOCITY_D:
	{
		double linearMotorXVelocity = 0;
		double linearMotorYVelocity = 0;
		double linearMotorZVelocity = 0;
		stream->read(linearMotorXVelocity);
		stream->read(linearMotorYVelocity);
		stream->read(linearMotorZVelocity);
		sixdofRestraint->setLinearMotorVelocity(0, (BReal)linearMotorXVelocity);
		sixdofRestraint->setLinearMotorVelocity(1, (BReal)linearMotorYVelocity);
		sixdofRestraint->setLinearMotorVelocity(2, (BReal)linearMotorZVelocity);

		double angularMotorXVelocity = 0;
		double angularMotorYVelocity = 0;
		double angularMotorZVelocity = 0;
		stream->read(angularMotorXVelocity);
		stream->read(angularMotorYVelocity);
		stream->read(angularMotorZVelocity);
		sixdofRestraint->setAngularMotorVelocity(0, (BReal)angularMotorXVelocity);
		sixdofRestraint->setAngularMotorVelocity(1, (BReal)angularMotorYVelocity);
		sixdofRestraint->setAngularMotorVelocity(2, (BReal)angularMotorZVelocity);
		break;
	}
	case SIGN_MOTOR_MAXFORCE:
	{
		float linearMotorXForce = 0;
		float linearMotorYForce = 0;
		float linearMotorZForce = 0;
		stream->read(linearMotorXForce);
		stream->read(linearMotorYForce);
		stream->read(linearMotorZForce);
		sixdofRestraint->setLinearMotorMaxForce(0, (BReal)linearMotorXForce);
		sixdofRestraint->setLinearMotorMaxForce(1, (BReal)linearMotorYForce);
		sixdofRestraint->setLinearMotorMaxForce(2, (BReal)linearMotorZForce);

		float angularMotorXForce = 0;
		float angularMotorYForce = 0;
		float angularMotorZForce = 0;
		stream->read(angularMotorXForce);
		stream->read(angularMotorYForce);
		stream->read(angularMotorZForce);
		sixdofRestraint->setAngularMotorMaxForce(0, (BReal)angularMotorXForce);
		sixdofRestraint->setAngularMotorMaxForce(1, (BReal)angularMotorYForce);
		sixdofRestraint->setAngularMotorMaxForce(2, (BReal)angularMotorZForce);
		break;
	}
	case SIGN_MOTOR_MAXFORCE_D:
	{
		double linearMotorXForce = 0;
		double linearMotorYForce = 0;
		double linearMotorZForce = 0;
		stream->read(linearMotorXForce);
		stream->read(linearMotorYForce);
		stream->read(linearMotorZForce);
		sixdofRestraint->setLinearMotorMaxForce(0, (BReal)linearMotorXForce);
		sixdofRestraint->setLinearMotorMaxForce(1, (BReal)linearMotorYForce);
		sixdofRestraint->setLinearMotorMaxForce(2, (BReal)linearMotorZForce);

		double angularMotorXForce = 0;
		double angularMotorYForce = 0;
		double angularMotorZForce = 0;
		stream->read(angularMotorXForce);
		stream->read(angularMotorYForce);
		stream->read(angularMotorZForce);
		sixdofRestraint->setAngularMotorMaxForce(0, (BReal)angularMotorXForce);
		sixdofRestraint->setAngularMotorMaxForce(1, (BReal)angularMotorYForce);
		sixdofRestraint->setAngularMotorMaxForce(2, (BReal)angularMotorZForce);
		break;
	}
	default:
		return false;
	}
	return true;
}
bool member_BObcDocument::readFixedRestraint(const Chunk& chunk, BFixedRestraint* fixedRestraint)
{
	switch (chunk.sign)
	{
	case SIGN_ROTATION:
	{
		BVectorf rotation = 0;
		stream->read(rotation);
		fixedRestraint->setRotation(rotation);
		break;
	}
	case SIGN_ROTATION_D:
	{
		BVectord rotation = 0;
		stream->read(rotation);
		fixedRestraint->setRotation(rotation);
		break;
	}
	default:
		return false;
	}
	return true;
}
bool member_BObcDocument::readGearRestraint(const Chunk& chunk, BGearRestraint* gearRestraint)
{
	switch (chunk.sign)
	{
	case SIGN_AXISA:
	{
		BVectorf axisA;
		stream->read(axisA);
		gearRestraint->setAxisA(axisA);
		break;
	}
	case SIGN_AXISA_D:
	{
		BVectord axisA;
		stream->read(axisA);
		gearRestraint->setAxisA(axisA);
		break;
	}
	case SIGN_AXISB:
	{
		BVectorf axisB;
		stream->read(axisB);
		gearRestraint->setAxisB(axisB);
		break;
	}
	case SIGN_AXISB_D:
	{
		BVectord axisB;
		stream->read(axisB);
		gearRestraint->setAxisB(axisB);
		break;
	}
	case SIGN_RATIO:
	{
		float ratio = 0;
		stream->read(ratio);
		gearRestraint->setRatio(ratio);
		break;
	}
	case SIGN_RATIO_D:
	{
		double ratio = 0;
		stream->read(ratio);
		gearRestraint->setRatio((BReal)ratio);
		break;
	}
	case SIGN_MOTOR_ENABLED:
	{
		bool enabled = false;
		stream->read(enabled);
		//gearRestraint->setMotorEnabled(enabled);
		break;
	}
	case SIGN_MOTOR_TARGET:
	{
		float target;
		stream->read(target);
		//gearRestraint->setMotorTarget(target);
		break;
	}
	case SIGN_MOTOR_TARGET_D:
	{
		double target;
		stream->read(target);
		//gearRestraint->setMotorTarget((BReal)target);
		break;
	}
	case SIGN_MOTOR_VELOCITY:
	{
		float velocity;
		stream->read(velocity);
		//gearRestraint->setMotorVelocity(velocity);
		break;
	}
	case SIGN_MOTOR_VELOCITY_D:
	{
		double velocity;
		stream->read(velocity);
		//gearRestraint->setMotorVelocity((BReal)velocity);
		break;
	}
	case SIGN_MOTOR_MAXFORCE:
	{
		float maxImpulse;
		stream->read(maxImpulse);
		//gearRestraint->setMotorMaxForce(maxImpulse);
		break;
	}
	case SIGN_MOTOR_MAXFORCE_D:
	{
		double maxImpulse;
		stream->read(maxImpulse);
		//gearRestraint->setMotorMaxForce((BReal)maxImpulse);
		break;
	}
	default:
		return false;
	}
	return true;
}

bool member_BObcDocument::readShape(const Chunk& chunk, BShape* shape)
{
	switch (chunk.sign)
	{
	case SIGN_VISIBLE:
	{
		bool visible = true;
		stream->read(visible);
		shape->setVisible(visible);
		break;
	}
	case SIGN_LIGHTING:
	{
		bool lighting = false;
		stream->read(lighting);
		shape->setLighting(lighting);
		break;
	}
	case SIGN_CULLBACK:
	{
		bool cullback = false;
		stream->read(cullback);
		shape->setCullback(cullback);
		break;
	}
	case SIGN_DEPTHTEST:
	{
		bool depthTest = false;
		stream->read(depthTest);
		shape->setDepthTest(depthTest);
		break;
	}
	case SIGN_DEPTHOFFSET:
	{
		float depthOffset = 0.0f;
		stream->read(depthOffset);
		shape->setDepthOffset(depthOffset);
		break;
	}
	case SIGN_TRANSPARENT:
	{
		bool transparent = false;
		stream->read(transparent);
		shape->setTransparent(transparent);
		break;
	}
	case SIGN_NORMALIZE:
	{
		bool normalize = false;
		stream->read(normalize);
		shape->setNormalize(normalize);
		break;
	}
	case SIGN_POINTSMOOTH:
	{
		bool pointSmooth = false;
		stream->read(pointSmooth);
		shape->setPointSmooth(pointSmooth);
		break;
	}
	case SIGN_POINTSIZE:
	{
		float pointSize = 1.0f;
		stream->read(pointSize);
		shape->setPointSize(pointSize);
		break;
	}
	case SIGN_LINESMOOTH:
	{
		bool lineSmooth = false;
		stream->read(lineSmooth);
		shape->setLineSmooth(lineSmooth);
		break;
	}
	case SIGN_LINEWIDTH:
	{
		float lineWidth = 1.0f;
		stream->read(lineWidth);
		shape->setLineWidth(lineWidth);
		break;
	}
	case SIGN_POLYGONSMOOTH:
	{
		bool polySmooth = false;
		stream->read(polySmooth);
		shape->setPolySmooth(polySmooth);
		break;
	}
	case SIGN_POLYGONMODE:
	{
		char polyMode = Poly_Fill;
		stream->read(polyMode);
		shape->setPolyMode((PolyMode)polyMode);
		break;
	}
	case SIGN_MATRIX:
	{
		BMatrixf matrix;
		stream->read(matrix);
		shape->setMatrix(matrix);
		break;
	}
	case SIGN_MATRIX_D:
	{
		BMatrixd matrix;
		stream->read(matrix);
		shape->setMatrix(matrix);
		break;
	}
	case SIGN_COLOR:
	{
		BColor color;
		stream->read(color);
		shape->setColor(color);
		break;
	}
	case SIGN_MATERIAL:
	{
		BMaterial* material = (BMaterial*)this->read(chunk);
		shape->setMaterial(material);
		break;
	}
	case SIGN_IMAGE:
	{
		BTexture* texture = (BTexture*)this->read(chunk);
		shape->setTexture(texture);
		break;
	}
	case SIGN_PIXMAP:
	{
		BTexture* texture = (BTexture*)this->read(chunk);
		shape->setTexture(texture);
		break;
	}
	case SIGN_PROGRAM:
	{
		BProgram* program = (BProgram*)this->read(chunk);
		shape->setProgram(program);
		break;
	}
	case SIGN_PROXY:
	{
		BShape* proxy = (BShape*)boss->readObject();
		shape->setProxy(proxy);
		break;
	}
	default:
		return false;
	}
	return true;
}
bool member_BObcDocument::readMesh(const Chunk& chunk, BMesh* mesh)
{
	if (chunk.sign == SIGN_OPTIMIZED)
	{
		bool optimized = false;
		stream->read(optimized);
		mesh->setOptimized(optimized);
		return true;
	}
	if (chunk.sign == SIGN_VERTICES)
	{
		int size = 0;
		stream->read(size);
		stream->read(buffer, size * sizeof(BVectorf));
		mesh->setVertices(new BVectorArray((BVectorf*)buffer.data(), size));
		return true;
	}
	if (chunk.sign == SIGN_VERTICES_D)
	{
		int size = 0;
		stream->read(size);
		stream->read(buffer, size * sizeof(BVectord));
		mesh->setVertices(new BVectorArray((BVectord*)buffer.data(), size));
		return true;
	}
	if (chunk.sign == SIGN_NORMALS)
	{
		int size = 0;
		stream->read(size);
		stream->read(buffer, size * sizeof(BVectorf));
		mesh->setNormals(new BVectorArray((BVectorf*)buffer.data(), size));
		return true;
	}
	if (chunk.sign == SIGN_NORMALS_D)
	{
		int size = 0;
		stream->read(size);
		stream->read(buffer, size * sizeof(BVectord));
		mesh->setNormals(new BVectorArray((BVectord*)buffer.data(), size));
		return true;
	}
	if (chunk.sign == SIGN_TEXCOORDS)
	{
		int size = 0;
		stream->read(size);
		BCoordArray* texCoords = new BCoordArray(size);
		stream->read(texCoords->data(), size);
		mesh->setTexCoords(texCoords);
		return true;
	}
	if (chunk.sign == SIGN_FACES)
	{
		int size = 0;
		stream->read(size);
		BFaceArray* faces = new BFaceArray(size);
		stream->read(faces->data(), size);
		mesh->setFaces(faces);
		return true;
	}
	if (chunk.sign == SIGN_COLORS)
	{
		int size = 0;
		stream->read(size);
		BColorArray* colors = new BColorArray(size);
		stream->read(colors->data(), size);
		mesh->setColors(colors);
		return true;
	}
	return false;
}
bool member_BObcDocument::readGeometry(const Chunk& chunk, BGeometry* geometry)
{
	if (chunk.sign == SIGN_OPTIMIZED)
	{
		bool optimized = false;
		stream->read(optimized);
		geometry->setOptimized(optimized);
		return true;
	}
	if (chunk.sign == SIGN_VERTICES)
	{
		int size = 0;
		stream->read(size);
		stream->read(buffer, size * sizeof(BVectorf));
		geometry->setVertices(new BVectorArray((BVectorf*)buffer.data(), size));
		return true;
	}
	if (chunk.sign == SIGN_VERTICES_D)
	{
		int size = 0;
		stream->read(size);
		stream->read(buffer, size * sizeof(BVectord));
		geometry->setVertices(new BVectorArray((BVectord*)buffer.data(), size));
		return true;
	}
	if (chunk.sign == SIGN_NORMALS)
	{
		int size = 0;
		stream->read(size);
		stream->read(buffer, size * sizeof(BVectorf));
		geometry->setNormals(new BVectorArray((BVectorf*)buffer.data(), size));
		return true;
	}
	if (chunk.sign == SIGN_NORMALS_D)
	{
		int size = 0;
		stream->read(size);
		stream->read(buffer, size * sizeof(BVectord));
		geometry->setNormals(new BVectorArray((BVectord*)buffer.data(), size));
		return true;
	}
	if (chunk.sign == SIGN_TEXCOORDS)
	{
		int size = 0;
		stream->read(size);
		BCoordArray* texCoords = new BCoordArray(size);
		stream->read(texCoords->data(), size);
		geometry->setTexCoords(texCoords);
		return true;
	}
	if (chunk.sign == SIGN_ELEMENT)
	{
		BElement* element = (BElement*)this->read(chunk);
		geometry->addElement(element);
		return true;
	}
	BHolder<BObject> object = this->read(chunk);
	if (BElement* element = object.as<BElement>())
		return geometry->addElement(element);
	return false;
}
bool member_BObcDocument::readTextual(const Chunk& chunk, BTextual* textual)
{
	switch (chunk.sign)
	{
	case SIGN_WIDTH:
	{
		BSizef size = textual->size();
		stream->read(size.width());
		textual->setSize(size);
		break;
	}
	case SIGN_WIDTH_D:
	{
		BSized size = textual->size();
		stream->read(size.width());
		textual->setSize(size);
		break;
	}
	case SIGN_HEIGHT:
	{
		BSizef size = textual->size();
		stream->read(size.height());
		textual->setSize(size);
		break;
	}
	case SIGN_HEIGHT_D:
	{
		BSized size = textual->size();
		stream->read(size.height());
		textual->setSize(size);
		break;
	}
	case SIGN_ALIGN:
	{
		Align align = Align_None;
		stream->read(align);
		textual->setAlign(align);
		break;
	}
	case SIGN_FONT:
	{
		int fontSize = 0;
		stream->read(fontSize);
		BString family;
		stream->read(family);
		BFont* font = new BFont(family, fontSize);
		textual->setFont(font);
		break;
	}
	case SIGN_GLYPSIZE:
	{
		float glyphSize = 0.0f;
		stream->read(glyphSize);
		textual->setGlyphSize(glyphSize);
		break;
	}
	case SIGN_TEXT:
	{
		BString text;
		stream->read(text);
		textual->setText(text);
		break;
	}
	case SIGN_COLORS:
	{
		int size = 0;
		stream->read(size);
		BColorArray* colors = new BColorArray(size);
		stream->read(colors->data(), size);
		textual->setColors(colors);
		break;
	}
	default:
		return false;
	}
	return true;
}
bool member_BObcDocument::readBillboard(const Chunk& chunk, BBillboard* billboard)
{
	switch (chunk.sign)
	{
	case SIGN_AXIS:
	{
		BVectorf axis;
		stream->read(axis);
		billboard->setAxis(axis);
		break;
	}
	case SIGN_AXIS_D:
	{
		BVectord axis;
		stream->read(axis);
		billboard->setAxis(axis);
		break;
	}
	default:
		return false;
	}
	return true;
}
bool member_BObcDocument::readParticle(const Chunk& chunk, BParticle* particle)
{
	return true;
}
bool member_BObcDocument::readElement(const Chunk& chunk, BElement* element)
{
	switch (chunk.sign)
	{
	case SIGN_VISIBLE:
	{
		bool visible;
		stream->read(visible);
		element->setVisible(visible);
		break;
	}
	case SIGN_PRIMITIVE:
	{
		Primitive primitive = Primitive_None;
		stream->read(primitive);
		element->setPrimitive(primitive);
		break;
	}
	case SIGN_FIRST:
	{
		int first = 0;
		stream->read(first);
		element->setFirst(first);
		break;
	}
	case SIGN_COUNT:
	{
		int count = 0;
		stream->read(count);
		element->setCount(count);
		break;
	}
	case SIGN_INDICES:
	{
		int size = 0;
		stream->read(size);
		BIntArray* indices = new BIntArray(size);
		stream->read(indices->data(), size);
		element->setIndices(indices);
		break;
	}
	case SIGN_PIECES:
	{
		int size = 0;
		stream->read(size);
		BPieceArray* pieces = new BPieceArray(size);
		stream->read(pieces->data(), size);
		element->setPieces(pieces);
		break;
	}
	default:
		return false;
	}
	return true;
}

bool member_BObcDocument::readCube(const Chunk& chunk, BCube* cube)
{
	switch (chunk.sign)
	{
	case SIGN_LENGTH:
	{
		float length = 0.0f;
		stream->read(length);
		cube->setLength(length);
		break;
	}
	case SIGN_LENGTH_D:
	{
		double length = 0.0;
		stream->read(length);
		cube->setLength((BReal)length);
		break;
	}
	case SIGN_WIDTH:
	{
		float width = 0.0f;
		stream->read(width);
		cube->setWidth(width);
		break;
	}
	case SIGN_WIDTH_D:
	{
		double width = 0.0;
		stream->read(width);
		cube->setWidth((BReal)width);
		break;
	}
	case SIGN_HEIGHT:
	{
		float height = 0.0f;
		stream->read(height);
		cube->setHeight(height);
		break;
	}
	case SIGN_HEIGHT_D:
	{
		double height = 0.0;
		stream->read(height);
		cube->setHeight((BReal)height);
		break;
	}
	case SIGN_LENGTHSEGMENTS:
	{
		int lengthSegments = 0;
		stream->read(lengthSegments);
		cube->setLengthSegments(lengthSegments);
		break;
	}
	case SIGN_WIDTHSEGMENT:
	{
		int widthSegments = 0;
		stream->read(widthSegments);
		cube->setWidthSegments(widthSegments);
		break;
	}
	case SIGN_HEIGHTSEGMENT:
	{
		int heightSegments = 0;
		stream->read(heightSegments);
		cube->setHeightSegments(heightSegments);
		break;
	}
	default:
		return false;
	}
	return true;
}
bool member_BObcDocument::readCone(const Chunk& chunk, BCone* cone)
{
	switch (chunk.sign)
	{
	case SIGN_RADIUS:
	{
		float radius = 0.0f;
		stream->read(radius);
		cone->setRadius(radius);
		break;
	}
	case SIGN_RADIUS_D:
	{
		double radius = 0.0;
		stream->read(radius);
		cone->setRadius((BReal)radius);
		break;
	}
	case SIGN_HEIGHT:
	{
		float height = 0.0f;
		stream->read(height);
		cone->setHeight(height);
		break;
	}
	case SIGN_HEIGHT_D:
	{
		double height = 0.0;
		stream->read(height);
		cone->setHeight((BReal)height);
		break;
	}
	case SIGN_SIDES:
	{
		int sides = 0;
		stream->read(sides);
		cone->setSides(sides);
		break;
	}
	case SIGN_SEGMENTS:
	{
		int segments = 0;
		stream->read(segments);
		cone->setSegments(segments);
		break;
	}
	case SIGN_RADIUSSEGMENTS:
	{
		int radiusSegments = 0;
		stream->read(radiusSegments);
		cone->setBottomSegments(radiusSegments);
		break;
	}
	default:
		return false;
	}
	return true;
}
bool member_BObcDocument::readCylinder(const Chunk& chunk, BCylinder* cylinder)
{
	switch (chunk.sign)
	{
	case SIGN_RADIUS:
	{
		float radius = 0.0f;
		stream->read(radius);
		cylinder->setRadius(radius);
		break;
	}
	case SIGN_RADIUS_D:
	{
		double radius = 0.0;
		stream->read(radius);
		cylinder->setRadius((BReal)radius);
		break;
	}
	case SIGN_HEIGHT:
	{
		float height = 0.0f;
		stream->read(height);
		cylinder->setHeight(height);
		break;
	}
	case SIGN_HEIGHT_D:
	{
		double height = 0.0;
		stream->read(height);
		cylinder->setHeight((BReal)height);
		break;
	}
	case SIGN_SIDES:
	{
		int sides = 0;
		stream->read(sides);
		cylinder->setSides(sides);
		break;
	}
	case SIGN_HEIGHTSEGMENT:
	{
		int heightSegments = 0;
		stream->read(heightSegments);
		cylinder->setHeightSegments(heightSegments);
		break;
	}
	case SIGN_RADIUSSEGMENTS:
	{
		int radiusSegments = 0;
		stream->read(radiusSegments);
		cylinder->setRadiusSegments(radiusSegments);
		break;
	}
	default:
		return false;
	}
	return true;
}
bool member_BObcDocument::readSphere(const Chunk& chunk, BSphere* sphere)
{
	switch (chunk.sign)
	{
	case SIGN_RADIUS:
	{
		float radius = 0.0f;
		stream->read(radius);
		sphere->setRadius(radius);
		break;
	}
	case SIGN_RADIUS_D:
	{
		double radius = 0.0;
		stream->read(radius);
		sphere->setRadius((BReal)radius);
		break;
	}
	case SIGN_SIDES:
	{
		int sides = 0;
		stream->read(sides);
		sphere->setSides(sides);
		break;
	}
	case SIGN_SEGMENTS:
	{
		int segments = 0;
		stream->read(segments);
		sphere->setSegments(segments);
		break;
	}
	default:
		return false;
	}
	return true;
}
bool member_BObcDocument::readGeoSphere(const Chunk& chunk, BGeoSphere* geoSphere)
{
	switch (chunk.sign)
	{
	case SIGN_RADIUS:
	{
		float radius = 0.0f;
		stream->read(radius);
		geoSphere->setRadius(radius);
		break;
	}
	case SIGN_RADIUS_D:
	{
		double radius = 0.0;
		stream->read(radius);
		geoSphere->setRadius((BReal)radius);
		break;
	}
	case SIGN_SEGMENTS:
	{
		int segments = 0;
		stream->read(segments);
		geoSphere->setDivide(segments);
		break;
	}
	default:
		return false;
	}
	return true;
}
bool member_BObcDocument::readTube(const Chunk& chunk, BTube* tube)
{
	switch (chunk.sign)
	{
	case SIGN_RADIUS:
	{
		float radius = 0.0f;
		stream->read(radius);
		tube->setRadius(radius);
		break;
	}
	case SIGN_RADIUS_D:
	{
		double radius = 0.0;
		stream->read(radius);
		tube->setRadius((BReal)radius);
		break;
	}
	case SIGN_HEIGHT:
	{
		float height = 0.0f;
		stream->read(height);
		tube->setHeight(height);
		break;
	}
	case SIGN_HEIGHT_D:
	{
		double height = 0.0;
		stream->read(height);
		tube->setHeight((BReal)height);
		break;
	}
	case SIGN_THICKNESS:
	{
		float thickness = 0.0f;
		stream->read(thickness);
		tube->setThickness(thickness);
		break;
	}
	case SIGN_THICKNESS_D:
	{
		double thickness = 0.0;
		stream->read(thickness);
		tube->setThickness((BReal)thickness);
		break;
	}
	case SIGN_SIDES:
	{
		int sides = 0;
		stream->read(sides);
		tube->setSides(sides);
		break;
	}
	case SIGN_HEIGHTSEGMENT:
	{
		int heightSegments = 0;
		stream->read(heightSegments);
		tube->setHeightSegments(heightSegments);
		break;
	}
	case SIGN_RADIUSSEGMENTS:
	{
		int radiusSegments = 0;
		stream->read(radiusSegments);
		tube->setRadiusSegments(radiusSegments);
		break;
	}
	default:
		return false;
	}
	return true;
}
bool member_BObcDocument::readTorus(const Chunk& chunk, BTorus* torus)
{
	switch (chunk.sign)
	{
	case SIGN_RADIUS:
	{
		float radius = 0.0f;
		stream->read(radius);
		torus->setRadius(radius);
		break;
	}
	case SIGN_RADIUS_D:
	{
		double radius = 0.0;
		stream->read(radius);
		torus->setRadius((BReal)radius);
		break;
	}
	case SIGN_OUTERRADIUS:
	{
		float outerRadius = 0.0f;
		stream->read(outerRadius);
		torus->setOuterRadius(outerRadius);
		break;
	}
	case SIGN_OUTERRADIUS_D:
	{
		double outerRadius = 0.0;
		stream->read(outerRadius);
		torus->setOuterRadius((BReal)outerRadius);
		break;
	}
	case SIGN_SIDES:
	{
		int sides = 0;
		stream->read(sides);
		torus->setSides(sides);
		break;
	}
	case SIGN_SEGMENTS:
	{
		int segments = 0;
		stream->read(segments);
		torus->setSegments(segments);
		break;
	}
	default:
		return false;
	}
	return true;
}
bool member_BObcDocument::readSurface(const Chunk& chunk, BSurface* surface)
{
	switch (chunk.sign)
	{
	case SIGN_QUAD:
	{
		BQuadf quad;
		stream->read(quad);
		surface->setQuadEdges(quad);
		break;
	}
	case SIGN_QUAD_D:
	{
		BQuadd quad;
		stream->read(quad);
		surface->setQuadEdges(quad);
		break;
	}
	case SIGN_HORSEGMENT:
	{
		int horSegment = 0;
		stream->read(horSegment);
		surface->setHorizontalSegment(horSegment);
		break;
	}
	case SIGN_VERSEGMENT:
	{
		int verSegment = 0;
		stream->read(verSegment);
		surface->setVerticalSegment(verSegment);
		break;
	}
	default:
		return false;
	}
	return true;
}
bool member_BObcDocument::readTerrain(const Chunk& chunk, BTerrain* terrain)
{
	switch (chunk.sign)
	{
	case SIGN_ALIGN:
	{
		Align align = Align_None;
		stream->read(align);
		terrain->setAlign(align);
		break;
	}
	case SIGN_WIDTH:
	{
		float width = 0.0f;
		stream->read(width);
		terrain->setWidth(width);
		break;
	}
	case SIGN_WIDTH_D:
	{
		double width = 0.0;
		stream->read(width);
		terrain->setWidth((BReal)width);
		break;
	}
	case SIGN_HEIGHT:
	{
		float height = 0.0f;
		stream->read(height);
		terrain->setHeight(height);
		break;
	}
	case SIGN_HEIGHT_D:
	{
		double height = 0.0;
		stream->read(height);
		terrain->setHeight((BReal)height);
		break;
	}
	case SIGN_ELEVATION:
	{
		int rows = 0;
		int columns = 0;
		stream->read(rows);
		stream->read(columns);
		BFloatTable elevation(rows, columns);
		stream->read(elevation.data(), elevation.size());
		terrain->setElevation(elevation);
		break;
	}
	case SIGN_ELEVATION_D:
	{
		int rows = 0;
		int columns = 0;
		stream->read(rows);
		stream->read(columns);
		BDoubleTable elevation(rows, columns);
		stream->read(elevation.data(), elevation.size());
		terrain->setElevation(elevation);
		break;
	}
	default:
		return false;
	}
	return true;
}
bool member_BObcDocument::readCapsule(const Chunk& chunk, BCapsule* capsule)
{
	if (chunk.sign == SIGN_RADIUS)
	{
		float radius = 0.0f;
		stream->read(radius);
		capsule->setRadius(radius);
		return true;
	}
	if (chunk.sign == SIGN_RADIUS_D)
	{
		double radius = 0.0;
		stream->read(radius);
		capsule->setRadius((BReal)radius);
		return true;
	}
	if (chunk.sign == SIGN_HEIGHT)
	{
		float height = 0.0f;
		stream->read(height);
		capsule->setHeight(height);
		return true;
	}
	if (chunk.sign == SIGN_HEIGHT_D)
	{
		double height = 0.0;
		stream->read(height);
		capsule->setHeight((BReal)height);
		return true;
	}
	if (chunk.sign == SIGN_SIDES)
	{
		int sides = 0;
		stream->read(sides);
		capsule->setSides(sides);
		return true;
	}
	if (chunk.sign == SIGN_HEIGHTSEGMENT)
	{
		int heightSegments = 0;
		stream->read(heightSegments);
		capsule->setHeightSegments(heightSegments);
		return true;
	}
	if (chunk.sign == SIGN_RADIUSSEGMENTS)
	{
		int radiusSegments = 0;
		stream->read(radiusSegments);
		capsule->setRadiusSegments(radiusSegments);
		return true;
	}
	return false;
}
bool member_BObcDocument::readLineStripe(const Chunk& chunk, BLineStripe* lineStripe)
{
	if (chunk.sign == SIGN_VERTICES)
	{
		int size = 0;
		stream->read(size);
		stream->read(buffer, size * sizeof(BVectorf));
		lineStripe->setVertices(new BVectorArray((BVectorf*)buffer.data(), size));
		return true;
	}
	if (chunk.sign == SIGN_VERTICES_D)
	{
		int size = 0;
		stream->read(size);
		stream->read(buffer, size * sizeof(BVectord));
		lineStripe->setVertices(new BVectorArray((BVectord*)buffer.data(), size));
		return true;
	}
	if (chunk.sign == SIGN_RADIUS)
	{
		float radius = 0.0f;
		stream->read(radius);
		lineStripe->setRadius(radius);
		return true;
	}
	if (chunk.sign == SIGN_RADIUS_D)
	{
		double radius = 0;
		stream->read(radius);
		lineStripe->setRadius(radius);
		return true;
	}
	if (chunk.sign == SIGN_RADIUSES)
	{
		int size = 0;
		stream->read(size);
		float radius = 0.0f;
		for (int i = 0; i < size; i++)
		{
			stream->read(radius);
			lineStripe->setRadius(i, radius);
		}
		return true;
	}
	if (chunk.sign == SIGN_RADIUSES_D)
	{
		int size = 0;
		stream->read(size);
		double radius = 0;
		for (int i = 0; i < size; i++)
		{
			stream->read(radius);
			lineStripe->setRadius(i, radius);
		}
		return true;
	}
	if (chunk.sign == SIGN_CLOSELOOP)
	{
		bool closeLoop = false;
		stream->read(closeLoop);
		lineStripe->setCloseLoop(closeLoop);
		return true;
	}
	if (chunk.sign == SIGN_THICKNESS)
	{
		float thickness = 0;
		stream->read(thickness);
		lineStripe->setThickness(thickness);
		return true;
	}
	if (chunk.sign == SIGN_THICKNESS_D)
	{
		double thickness = 0;
		stream->read(thickness);
		lineStripe->setThickness(thickness);
		return true;
	}
	return false;
}
bool member_BObcDocument::readSplineCurve(const Chunk& chunk, BSplineCurve* splineCurve)
{
	if (chunk.sign == SIGN_VERTICES)
	{
		int size = 0;
		stream->read(size);
		stream->read(buffer, size * sizeof(BVectorf));
		splineCurve->setVertices(new BVectorArray((BVectorf*)buffer.data(), size));
		return true;
	}
	if (chunk.sign == SIGN_VERTICES_D)
	{
		int size = 0;
		stream->read(size);
		stream->read(buffer, size * sizeof(BVectord));
		splineCurve->setVertices(new BVectorArray((BVectord*)buffer.data(), size));
		return true;
	}
	if (chunk.sign == SIGN_CLOSELOOP)
	{
		bool closeLoop = false;
		stream->read(closeLoop);
		splineCurve->setCloseLoop(closeLoop);
		return true;
	}
	if (chunk.sign == SIGN_THICKNESS)
	{
		float thickness = 0;
		stream->read(thickness);
		splineCurve->setThickness(thickness);
		return true;
	}
	if (chunk.sign == SIGN_THICKNESS_D)
	{
		double thickness = 0;
		stream->read(thickness);
		splineCurve->setThickness(thickness);
		return true;
	}
	return false;
}

bool member_BObcDocument::readMaterial(const Chunk& chunk, BMaterial* material)
{
	switch (chunk.sign)
	{
	case SIGN_AMBIENT:
	{
		BColor ambient;
		stream->read(ambient);
		material->setAmbient(ambient);
		break;
	}
	case SIGN_DIFFUSE:
	{
		BColor diffuse;
		stream->read(diffuse);
		material->setDiffuse(diffuse);
		break;
	}
	case SIGN_SPECULAR:
	{
		BColor specular;
		stream->read(specular);
		material->setSpecular(specular);
		break;
	}
	case SIGN_EMISSION:
	{
		BColor emission;
		stream->read(emission);
		material->setEmission(emission);
		break;
	}
	case SIGN_SHININESS:
	{
		float shininess = 0;
		stream->read(shininess);
		material->setShininess(shininess);
		break;
	}
	default:
		return false;
	}
	return true;
}
bool member_BObcDocument::readTexture(const Chunk& chunk, BTexture* texture)
{
	switch (chunk.sign)
	{
	case SIGN_BLEND:
	{
		BTexture::Blend blend = BTexture::Blend_None;
		stream->read(blend);
		texture->setBlend(blend);
		break;
	}
	case SIGN_WRAP:
	{
		BTexture::Wrap wrap = BTexture::Wrap_None;
		stream->read(wrap);
		texture->setWrap(wrap);
		break;
	}
	case SIGN_FILTER:
	{
		BTexture::Filter filter = BTexture::Filter_None;
		stream->read(filter);
		texture->setFilter(filter);
		break;
	}
	case SIGN_MIPMAP:
	{
		bool mipmap = false;
		stream->read(mipmap);
		texture->setMipmap(mipmap);
		break;
	}
	case SIGN_BLENDCOLOR:
	{
		BColor blendColor;
		stream->read(blendColor);
		texture->setBlendColor(blendColor);
		break;
	}
	default:
		return false;
	}
	return true;
}
bool member_BObcDocument::readImage(const Chunk& chunk, BImage* image)
{
	switch (chunk.sign)
	{
	case SIGN_FILENAME:
	{
		BString fileName;
		stream->read(fileName);
		image->setFileName(fileName);
		if (chunk.end > (BUInt)stream->offset())
		{
			BReadWrite* rw = GetReadWrite(fileName.ext());
			if (!rw)
				rw = GetReadWrite(fileName.name());
			if (rw)
			{
				int size = chunk.end - stream->offset();
				BBuffer buffer(size);
				stream->read(buffer.bytes(), size);
				if (rw->read(buffer, image))
					break;
				message() << "OBC Error : Read image bytes failed : " << fileName;
			}
		}
		else
		{
			if (ReadFile(fileName, image))
				break;
			BString absFileName = BApplication::currentPath();
			absFileName << '/' << fileName;
			if (ReadFile(absFileName, image))
				break;
			message() << "OBC Error : Read image file failed : " << fileName;
		}
		break;
	}
	case SIGN_FORMAT:
	{
		Format format = Format_None;
		stream->read(format);
		image->setFormat(format);
		break;
	}
	case SIGN_SIZE:
	{
		BSize size;
		stream->read(size);
		image->setSize(size);
		break;
	}
	case SIGN_PIXELS:
	{
		int size = 0;
		stream->read(size);
		BByteArray* pixels = new BByteArray(size);
		stream->read(pixels->data(), size);
		image->setPixels(pixels);
		break;
	}
	default:
		return false;
	}
	return true;
}
bool member_BObcDocument::readPixmap(const Chunk& chunk, BPixmap* pixmap)
{
	switch (chunk.sign)
	{
	case SIGN_BLEND:
	{
		BTexture::Blend blend = BTexture::Blend_None;
		stream->read(blend);
		pixmap->setBlend(blend);
		break;
	}
	case SIGN_WRAP:
	{
		BTexture::Wrap wrap = BTexture::Wrap_None;
		stream->read(wrap);
		pixmap->setWrap(wrap);
		break;
	}
	case SIGN_FILTER:
	{
		BTexture::Filter filter = BTexture::Filter_None;
		stream->read(filter);
		pixmap->setFilter(filter);
		break;
	}
	case SIGN_MIPMAP:
	{
		bool mipmap = false;
		stream->read(mipmap);
		pixmap->setMipmap(mipmap);
		break;
	}
	case SIGN_BLENDCOLOR:
	{
		BColor blendColor;
		stream->read(blendColor);
		pixmap->setBlendColor(blendColor);
		break;
	}
	case SIGN_SIZE:
	{
		BSize size;
		stream->read(size);
		pixmap->setSize(size);
		break;
	}
	case SIGN_BACKGROUND:
	{
		BColor background;
		stream->read(background);
		pixmap->setColor(background);
		break;
	}
	default:
		return false;
	}
	return true;
}
bool member_BObcDocument::readProgram(const Chunk& chunk, BProgram* program)
{
	switch (chunk.sign)
	{
	case SIGN_SHADER:
	{
		BShader* shader = (BShader*)this->read(chunk);
		program->addShader(shader);
		break;
	}
	case SIGN_UNIFORM:
	{
		BUniform* uniform = (BUniform*)this->read(chunk);
		program->addUniform(uniform);
		break;
	}
	default:
		return false;
	}
	return true;
}
bool member_BObcDocument::readShader(const Chunk& chunk, BShader* shader)
{
	switch (chunk.sign)
	{
	case SIGN_TYPE:
	{
		BShader::Type type = BShader::Type_None;
		stream->read(type);
		shader->setType(type);
		break;
	}
	case SIGN_TEXT:
	{
		BString text;
		stream->read(text);
		shader->setText(text);
		break;
	}
	default:
		return false;
	}
	return true;
}
bool member_BObcDocument::readUniform(const Chunk& chunk, BUniform* uniform)
{
	switch (chunk.sign)
	{
	case SIGN_TYPE:
	{
		BUniform::Type type = BUniform::Type_None;
		stream->read(type);
		uniform->setType(type);
		break;
	}
	case SIGN_SIZE:
	{
		int size = 0;
		stream->read(size);
		uniform->setSize(size);
		break;
	}
	default:
		return false;
	}
	return true;
}
bool member_BObcDocument::readScript(const Chunk& chunk, BScript* script)
{
	switch (chunk.sign)
	{
	case SIGN_PATH:
	{
		BString path;
		stream->read(path);
		script->setPath(path);
		return true;
	}
	case SIGN_SOURCE:
	{
		BSource* source = (BSource*)this->read(chunk);
		script->insertSource(source);
		return true;
	}
	case SIGN_BREAKPOINTS:
	{
		BString text;
		int count = 0;
		stream->read(count);
		for (int i = 0; i < count; i++)
		{
			stream->read(text);
			script->insertBreakpoint(text);
		}
		return true;
	}
	case SIGN_SEQUENCE:
	{
		int size = 0;
		stream->read(size);
		BExpHolderArray sequence(size);
		Chunk expChunk;
		for (int i = 0; i < size; i++)
		{
			sequence[i] = new BExp();
			readBeginChunk(expChunk, chunk.end);
			readExp(expChunk, sequence[i]);
			readEndChunk(expChunk);
		}
		script->setSequence(sequence);
		const BString& message = script->message();
		if (message.size())
		{
			puts(message.c_str());
		}
		return true;
	}
	default:
		return false;
	}
}
bool member_BObcDocument::readSource(const Chunk& chunk, BSource* source)
{
	switch (chunk.sign)
	{
	case SIGN_FILENAME:
	{
		BString fileName;
		stream->read(fileName);
		source->setFileName(fileName);
		return true;
	}
	case SIGN_TEXT:
	{
		BString text;
		stream->read(text);
		source->setText(text);
		return true;
	}
	default:
		return false;
	}
}
bool member_BObcDocument::readExp(const Chunk& chunk, BExp* exp)
{
	BString type;
	Chunk sub;
	while (readBeginChunk(sub, chunk.end))
	{
		switch (sub.sign)
		{
		case SIGN_NAME:
			stream->read(exp->name);
			break;
		case SIGN_SYNTAX:
			stream->read(exp->syntax);
			break;
		case SIGN_INFORMATION:
			stream->read(exp->info);
			break;
		case SIGN_TYPE:
			stream->read(exp->type);
			break;
		case SIGN_VALUE:
		{
			stream->read(type);
			if (type == "bool")
			{
				exp->value.fill<bool>();
				stream->read((bool&)exp->value);
			}
			else if (type == "char")
			{
				exp->value.fill<char>();
				stream->read((char&)exp->value);
			}
			else if (type == "short")
			{
				exp->value.fill<short>();
				stream->read((short&)exp->value);
			}
			else if (type == "int")
			{
				exp->value.fill<int>();
				stream->read((int&)exp->value);
			}
			else if (type == "long")
			{
				exp->value.fill<long long>();
				stream->read((long long&)exp->value);
			}
			else if (type == "float")
			{
				exp->value.fill<float>();
				stream->read((float&)exp->value);
			}
			else if (type == "double")
			{
				exp->value.fill<double>();
				stream->read((double&)exp->value);
			}
			else if (type == "string")
			{
				exp->value.fill<BString>();
				stream->read((BString&)exp->value);
			}
			break;
		}
		case SIGN_EXP:
		{
			BExp* child = new BExp();
			readExp(sub, child);
			exp->params.append(child);
			break;
		}
		default:
			return false;
		}
		readEndChunk(sub);
	}
	return true;
}

bool member_BObcDocument::readSonNode(const Chunk& chunk, BSonNode* sonNode)
{
	if (chunk.sign == SIGN_FORMAT)
	{
		BString format;
		stream->read(format);
		sonNode->setFormat(format);
		return true;
	}
	if (chunk.sign == SIGN_TEXT)
	{
		BString text;
		stream->read(text);
		sonNode->setText(text);
		return true;
	}
	if (chunk.sign == SIGN_ATTRIB)
	{
		BString key;
		stream->read(key);
		BString value;
		stream->read(value);
		sonNode->setAttrib(key, value);
		return true;
	}
	if (chunk.sign == SIGN_SONNODE)
	{
		BSonNode* child = (BSonNode*)this->read(chunk);
		sonNode->addChild(child);
		return true;
	}
	return false;
}
bool member_BObcDocument::readXmlNode(const Chunk& chunk, BXmlNode* xmlNode)
{
	if (chunk.sign == SIGN_FORMAT)
	{
		BString format;
		stream->read(format);
		xmlNode->setFormat(format);
		return true;
	}
	if (chunk.sign == SIGN_TEXT)
	{
		BString text;
		stream->read(text);
		xmlNode->setText(text);
		return true;
	}
	if (chunk.sign == SIGN_ATTRIB)
	{
		BString key;
		stream->read(key);
		BString value;
		stream->read(value);
		xmlNode->setAttrib(key, value);
		return true;
	}
	if (chunk.sign == SIGN_XMLNODE)
	{
		BXmlNode* child = (BXmlNode*)this->read(chunk);
		xmlNode->addChild(child);
		return true;
	}
	return false;
}

bool member_BObcDocument::writeObject(const BObject* object)
{
	const BString& name = object->name();
	if (name.size())
	{
		AutoChunk chunk(this, SIGN_NAME);
		stream->write(name);
	}
	{
		AutoChunk chunk(this, SIGN_ENABLED);
		stream->write(object->enabled());
	}
	return true;
}
bool member_BObcDocument::writeScene(const BScene* scene)
{
	{
		AutoChunk chunk(this, SIGN_OPTIMIZED);
		bool optimized = scene->optimized();
		stream->write(optimized);
	}
	for (int i = 0; i < scene->shapeCount(); i++)
	{
		const BShape* shape = scene->shape(i);
		if (!write(shape))
		{
			return false;
		}
	}
	for (int i = 0; i < scene->nodeCount(); i++)
	{
		const BNode* node = scene->node(i);
		if (!write(node))
		{
			return false;
		}
	}
	for (int i = 0; i < scene->groupCount(); i++)
	{
		const BGroup* group = scene->group(i);
		if (!write(group))
		{
			return false;
		}
	}
	for (int i = 0; i < scene->restraintCount(); i++)
	{
		const BRestraint* restraint = scene->restraint(i);
		if (!write(restraint))
		{
			return false;
		}
	}
	return true;
}
bool member_BObcDocument::writeGroup(const BGroup* group)
{
	{
		AutoChunk chunk(this, SIGN_VISIBLE);
		stream->write(group->visible());
	}
	for (int i = 0; i < group->shapeCount(); i++)
	{
		const BShape* shape = group->shape(i);
		if (!write(shape))
		{
			return false;
		}
	}
	for (int i = 0; i < group->nodeCount(); i++)
	{
		const BNode* node = group->node(i);
		if (!write(node))
		{
			return false;
		}
	}
	for (int i = 0; i < group->childCount(); i++)
	{
		const BGroup* childGroup = group->child(i);
		if (!write(childGroup))
		{
			return false;
		}
	}
	for (int i = 0; i < group->restraintCount(); i++)
	{
		const BRestraint* restraint = group->restraint(i);
		if (!write(restraint))
		{
			return false;
		}
	}
	return true;
}
bool member_BObcDocument::writeNode(const BNode* node)
{
	{
		AutoChunk chunk(this, SIGN_VISIBLE);
		stream->write(node->visible());
	}
	{
		AutoChunk chunk(this, SIGN_OPTIMIZED);
		stream->write(node->optimized());
	}
	{
		AutoChunk chunk(this, SIGN_MATRIX);
		stream->write(node->matrix());
	}
	for (int i = 0; i < node->shapeCount(); i++)
	{
		const BShape* shape = node->shape(i);
		write(shape);
	}
	return true;
}
bool member_BObcDocument::writeLight(const BLight* light)
{
	{
		AutoChunk chunk(this, SIGN_AMBIENT);
		BColor ambient = light->ambient();
		stream->write(ambient);
	}
	{
		AutoChunk chunk(this, SIGN_DIFFUSE);
		BColor diffuse = light->diffuse();
		stream->write(diffuse);
	}
	{
		AutoChunk chunk(this, SIGN_SPECULAR);
		BColor specular = light->specular();
		stream->write(specular);
	}
	{
		AutoChunk chunk(this, SIGN_ATTENUATION);
		float attenuation = light->attenuation();
		stream->write(attenuation);
	}
	{
		AutoChunk chunk(this, SIGN_ATTENUATION2);
		float attenuation2 = light->attenuation2();
		stream->write(attenuation2);
	}
	{
		AutoChunk chunk(this, SIGN_CUTOFF);
		float cutoff = light->cutoff();
		stream->write(cutoff);
	}
	{
		AutoChunk chunk(this, SIGN_EXPONENT);
		float exponent = light->exponent();
		stream->write(exponent);
	}
	{
		AutoChunk chunk(this, SIGN_RADIUS);
		BReal radius = light->radius();
		stream->write(radius);
	}
	return true;
}
bool member_BObcDocument::writeCamera(const BCamera* camera)
{
	{
		AutoChunk chunk(this, SIGN_ORTHO);
		bool ortho = camera->ortho();
		stream->write(ortho);
	}
	{
		AutoChunk chunk(this, SIGN_CENTER);
		BVector center = camera->center();
		stream->write(center);
	}
	{
		AutoChunk chunk(this, SIGN_UP);
		BVector up = camera->up();
		stream->write(up);
	}
	{
		AutoChunk chunk(this, SIGN_NEAR);
		double near = camera->near();
		stream->write(near);
	}
	{
		AutoChunk chunk(this, SIGN_FAR);
		double far = camera->far();
		stream->write(far);
	}
	{
		AutoChunk chunk(this, SIGN_FOVY);
		double fovy = camera->fovy();
		stream->write(fovy);
	}
	{
		AutoChunk chunk(this, SIGN_LENSSIZE);
		double lensWidth = camera->lensWidth();
		stream->write(lensWidth);
		double lensHeight = camera->lensHeight();
		stream->write(lensHeight);
	}
	{
		AutoChunk chunk(this, SIGN_PIXELSIZE);
		int pixelWidth = camera->pixelWidth();
		stream->write(pixelWidth);
		int pixelHeight = camera->pixelHeight();
		stream->write(pixelHeight);
	}
	{
		AutoChunk chunk(this, SIGN_PIXELPOLICY);
		Policy pixelPolicy = camera->pixelSizePolicy();
		stream->write(pixelPolicy);
	}
	{
		AutoChunk chunk(this, SIGN_BACKGROUND);
		const BColor& color = camera->color();
		stream->write(color);
	}
	return true;
}
bool member_BObcDocument::writeBody(const BBody* body)
{
	{
		AutoChunk chunk(this, SIGN_DEACTIME);
		BReal deactivatedTime = body->deactivatedTime();
		stream->write(deactivatedTime);
	}
	{
		AutoChunk chunk(this, SIGN_MASS);
		BReal mass = body->mass();
		stream->write(mass);
	}
	{
		AutoChunk chunk(this, SIGN_INERTIA);
		const BVector& inertia = body->inertia();
		stream->write(inertia);
	}
	{
		AutoChunk chunk(this, SIGN_RESTITUTION);
		BReal restitution = body->restitution();
		stream->write(restitution);
	}
	{
		AutoChunk chunk(this, SIGN_GRAVITY);
		const BVector& gravity = body->gravity();
		stream->write(gravity);
	}
	{
		AutoChunk chunk(this, SIGN_FRICTION);
		BReal friction = body->friction();
		BReal rollingFriction = body->rollingFriction();
		stream->write(friction);
		stream->write(rollingFriction);
	}
	{
		AutoChunk chunk(this, SIGN_FORCE);
		const BVector& force = body->force();
		stream->write(force);
	}
	{
		AutoChunk chunk(this, SIGN_LINEAR_THRESHOLD);
		BReal sleepingThreshold = body->linearThreshold();
		stream->write(sleepingThreshold);
	}
	{
		AutoChunk chunk(this, SIGN_ANGULAR_THRESHOLD);
		BReal sleepingThreshold = body->angularThreshold();
		stream->write(sleepingThreshold);
	}
	{
		AutoChunk chunk(this, SIGN_LINEAR_VELOCITY);
		const BVector& linearVelocity = body->linearVelocity();
		stream->write(linearVelocity);
	}
	{
		AutoChunk chunk(this, SIGN_ANGULAR_VELOCITY);
		const BVector& angularVelocity = body->angularVelocity();
		stream->write(angularVelocity);
	}
	return true;
}
bool member_BObcDocument::writeSoftBody(const BSoftBody* softBody)
{
	return true;
}

bool member_BObcDocument::writeRestraint(const BRestraint* restraint)
{
	if (BNode* nodeA = restraint->bodyA())
	{
		AutoChunk chunk(this, SIGN_NODEA_ID);
		int id = writeObjectMap(nodeA);
		stream->write(id);
	}
	{
		AutoChunk chunk(this, SIGN_PIVOTA);
		const BVector& pointA = restraint->pivotA();
		stream->write(pointA);
	}
	if (BNode* nodeB = restraint->bodyB())
	{
		AutoChunk chunk(this, SIGN_NODEB_ID);
		int id = writeObjectMap(nodeB);
		stream->write(id);
	}
	{
		AutoChunk chunk(this, SIGN_PIVOTB);
		const BVector& pointB = restraint->pivotB();
		stream->write(pointB);
	}
	{
		AutoChunk chunk(this, SIGN_COLLIDING);
		bool colliding = restraint->colliding();
		stream->write(colliding);
	}
	{
		AutoChunk chunk(this, SIGN_BREAK_IMPULSE);
		BReal breakImpulse = restraint->breakImpulse();
		stream->write(breakImpulse);
	}
	return true;
}
bool member_BObcDocument::writePointRestraint(const BPointRestraint* pointRestraint)
{
	{
		AutoChunk chunk(this, SIGN_DAMPING);
		BReal damping = pointRestraint->damping();
		stream->write(damping);
	}
	{
		AutoChunk chunk(this, SIGN_IMPULSE_LIMIT_D);
		BReal impulseLimit = pointRestraint->impulseLimit();
		stream->write(impulseLimit);
	}
	return true;
}
bool member_BObcDocument::writeHingeRestraint(const BHingeRestraint* hingeRestraint)
{
	{
		AutoChunk chunk(this, SIGN_AXISA);
		const BVector& axisA = hingeRestraint->axisA();
		stream->write(axisA);
	}
	{
		AutoChunk chunk(this, SIGN_AXISB);
		const BVector& axisB = hingeRestraint->axisB();
		stream->write(axisB);
	}
	{
		AutoChunk chunk(this, SIGN_ANGULAR_LIMIT);
		const BRealRange& angleRange = hingeRestraint->angularLimit();
		stream->write(angleRange);
	}
	{
		AutoChunk chunk(this, SIGN_MOTOR_ENABLED);
		bool enabled = hingeRestraint->motorEnabled();
		stream->write(enabled);
	}
	{
		AutoChunk chunk(this, SIGN_MOTOR_TARGET);
		BReal target = hingeRestraint->motorTarget();
		stream->write(target);
	}
	{
		AutoChunk chunk(this, SIGN_MOTOR_MAXFORCE);
		BReal motorMaxForce = hingeRestraint->motorMaxForce();
		stream->write(motorMaxForce);
	}
	{
		AutoChunk chunk(this, SIGN_MOTOR_VELOCITY);
		BReal velocity = hingeRestraint->motorVelocity();
		stream->write(velocity);
	}
	return true;
}
bool member_BObcDocument::writeSliderRestraint(const BSliderRestraint* sliderRestraint)
{
	if (BLineStripe* stripe = sliderRestraint->stripe())
	{
		write(stripe);
	}
	if (BSplineCurve* curve = sliderRestraint->curve())
	{
		write(curve);
	}
	{
		AutoChunk chunk(this, SIGN_AXISA);
		const BVector& axisA = sliderRestraint->axisA();
		stream->write(axisA);
	}
	{
		AutoChunk chunk(this, SIGN_AXISB);
		const BVector& axisB = sliderRestraint->axisB();
		stream->write(axisB);
	}
	{
		AutoChunk chunk(this, SIGN_LINEAR_LIMIT);
		const BRealRange& linearLimit = sliderRestraint->linearLimit();
		stream->write(linearLimit);
	}
	{
		AutoChunk chunk(this, SIGN_ANGULAR_LIMIT);
		const BRealRange& angularLimit = sliderRestraint->angularLimit();
		stream->write(angularLimit);
	}
	{
		AutoChunk chunk(this, SIGN_LINEAR_MOTOR_ENABLED);
		bool enabled = sliderRestraint->linearMotorEnabled();
		stream->write(enabled);
	}
	{
		AutoChunk chunk(this, SIGN_LINEAR_MOTOR_TARGET);
		BReal motorTarget = sliderRestraint->linearMotorTarget();
		stream->write(motorTarget);
	}
	{
		AutoChunk chunk(this, SIGN_LINEAR_MOTOR_VELOCITY);
		BReal motorVelocity = sliderRestraint->linearMotorVelocity();
		stream->write(motorVelocity);
	}
	{
		AutoChunk chunk(this, SIGN_LINEAR_MOTOR_MAXFORCE);
		BReal motorMaxForce = sliderRestraint->linearMotorMaxForce();
		stream->write(motorMaxForce);
	}
	{
		AutoChunk chunk(this, SIGN_ANGULAR_MOTOR_ENABLED);
		bool enabled = sliderRestraint->angularMotorEnabled();
		stream->write(enabled);
	}
	{
		AutoChunk chunk(this, SIGN_ANGULAR_MOTOR_TARGET);
		BReal motorTarget = sliderRestraint->angularMotorTarget();
		stream->write(motorTarget);
	}
	{
		AutoChunk chunk(this, SIGN_ANGULAR_MOTOR_VELOCITY);
		BReal motorVelocity = sliderRestraint->angularMotorVelocity();
		stream->write(motorVelocity);
	}
	{
		AutoChunk chunk(this, SIGN_ANGULAR_MOTOR_MAXFORCE);
		BReal motorMaxForce = sliderRestraint->angularMotorMaxForce();
		stream->write(motorMaxForce);
	}

	return true;
}
bool member_BObcDocument::writeConearRestraint(const BConearRestraint* conearRestraint)
{
	{
		AutoChunk chunk(this, SIGN_DAMPING);
		BReal damping = conearRestraint->damping();
		stream->write(damping);
	}
	{
		AutoChunk chunk(this, SIGN_AXISA);
		BVector axisA = conearRestraint->axisA();
		stream->write(axisA);
	}
	{
		AutoChunk chunk(this, SIGN_AXISB);
		BVector axisB = conearRestraint->axisB();
		stream->write(axisB);
	}
	return false;
}
bool member_BObcDocument::writeSixdofRestraint(const BSixdofRestraint* sixdofRestraint)
{
	{
		AutoChunk chunk(this, SIGN_LINEAR_LIMIT);
		const BVector& linearLowerLimit = sixdofRestraint->linearLowerLimit();
		const BVector& linearUpperLimit = sixdofRestraint->linearUpperLimit();
		stream->write(linearLowerLimit);
		stream->write(linearUpperLimit);
	}
	{
		AutoChunk chunk(this, SIGN_ANGULAR_LIMIT);
		const BVector& angularLowerLimit = sixdofRestraint->angularLowerLimit();
		const BVector& angularUpperLimit = sixdofRestraint->angularUpperLimit();
		stream->write(angularLowerLimit);
		stream->write(angularUpperLimit);
	}
	{
		AutoChunk chunk(this, SIGN_MOTOR_ENABLED);
		bool linearMotorXEnabled = sixdofRestraint->linearMotorEnabled(0);
		bool linearMotorYEnabled = sixdofRestraint->linearMotorEnabled(1);
		bool linearMotorZEnabled = sixdofRestraint->linearMotorEnabled(2);
		stream->write(linearMotorXEnabled);
		stream->write(linearMotorYEnabled);
		stream->write(linearMotorZEnabled);

		bool angularMotorXEnabled = sixdofRestraint->angularMotorEnabled(0);
		bool angularMotorYEnabled = sixdofRestraint->angularMotorEnabled(1);
		bool angularMotorZEnabled = sixdofRestraint->angularMotorEnabled(2);
		stream->write(angularMotorXEnabled);
		stream->write(angularMotorYEnabled);
		stream->write(angularMotorZEnabled);
	}
	{
		AutoChunk chunk(this, SIGN_MOTOR_TARGET);
		BReal linearMotorXTarget = sixdofRestraint->linearMotorTarget(0);
		BReal linearMotorYTarget = sixdofRestraint->linearMotorTarget(1);
		BReal linearMotorZTarget = sixdofRestraint->linearMotorTarget(2);
		stream->write(linearMotorXTarget);
		stream->write(linearMotorYTarget);
		stream->write(linearMotorZTarget);

		BReal angularMotorXTarget = sixdofRestraint->angularMotorTarget(0);
		BReal angularMotorYTarget = sixdofRestraint->angularMotorTarget(1);
		BReal angularMotorZTarget = sixdofRestraint->angularMotorTarget(2);
		stream->write(angularMotorXTarget);
		stream->write(angularMotorYTarget);
		stream->write(angularMotorZTarget);
	}
	{
		AutoChunk chunk(this, SIGN_MOTOR_VELOCITY);
		BReal linearMotorXVelocity = sixdofRestraint->linearMotorVelocity(0);
		BReal linearMotorYVelocity = sixdofRestraint->linearMotorVelocity(1);
		BReal linearMotorZVelocity = sixdofRestraint->linearMotorVelocity(2);
		stream->write(linearMotorXVelocity);
		stream->write(linearMotorYVelocity);
		stream->write(linearMotorZVelocity);

		BReal angularMotorXVelocity = sixdofRestraint->angularMotorVelocity(0);
		BReal angularMotorYVelocity = sixdofRestraint->angularMotorVelocity(1);
		BReal angularMotorZVelocity = sixdofRestraint->angularMotorVelocity(2);
		stream->write(angularMotorXVelocity);
		stream->write(angularMotorYVelocity);
		stream->write(angularMotorZVelocity);
	}
	{
		AutoChunk chunk(this, SIGN_MOTOR_MAXFORCE);
		BReal linearMotorXForce = sixdofRestraint->linearMotorMaxForce(0);
		BReal linearMotorYForce = sixdofRestraint->linearMotorMaxForce(1);
		BReal linearMotorZForce = sixdofRestraint->linearMotorMaxForce(2);
		stream->write(linearMotorXForce);
		stream->write(linearMotorYForce);
		stream->write(linearMotorZForce);

		BReal angularMotorXForce = sixdofRestraint->angularMotorMaxForce(0);
		BReal angularMotorYForce = sixdofRestraint->angularMotorMaxForce(1);
		BReal angularMotorZForce = sixdofRestraint->angularMotorMaxForce(2);
		stream->write(angularMotorXForce);
		stream->write(angularMotorYForce);
		stream->write(angularMotorZForce);
	}

	return true;
}
bool member_BObcDocument::writeFixedRestraint(const BFixedRestraint* fixedRestraint)
{
	{
		AutoChunk chunk(this, SIGN_ROTATION);
		const BVector& rotate = fixedRestraint->rotation();
		stream->write(rotate);
	}
	return true;
}
bool member_BObcDocument::writeGearRestraint(const BGearRestraint* gearRestraint)
{
	{
		AutoChunk chunk(this, SIGN_AXISA);
		const BVector& axisA = gearRestraint->axisA();
		stream->write(axisA);
	}
	{
		AutoChunk chunk(this, SIGN_AXISB);
		const BVector& axisB = gearRestraint->axisB();
		stream->write(axisB);
	}
	{
		AutoChunk chunk(this, SIGN_RATIO);
		BReal ratio = gearRestraint->ratio();
		stream->write(ratio);
	}
	return true;
}

bool member_BObcDocument::writeShape(const BShape* shape)
{
	{
		bool visible = shape->visible();
		AutoChunk chunk(this, SIGN_VISIBLE);
		stream->write(visible);
	}
	{
		bool lighting = shape->lighting();
		AutoChunk chunk(this, SIGN_LIGHTING);
		stream->write(lighting);
	}
	{
		bool cullback = shape->cullback();
		AutoChunk chunk(this, SIGN_CULLBACK);
		stream->write(cullback);
	}
	{
		bool depthTest = shape->depthTest();
		AutoChunk chunk(this, SIGN_DEPTHTEST);
		stream->write(depthTest);
	}
	{
		AutoChunk chunk(this, SIGN_DEPTHOFFSET);
		float depthOffset = shape->depthOffset();
		stream->write(depthOffset);
	}
	{
		bool pointSmooth = shape->pointSmooth();
		AutoChunk chunk(this, SIGN_POINTSMOOTH);
		stream->write(pointSmooth);
	}
	{
		bool lineSmooth = shape->lineSmooth();
		AutoChunk chunk(this, SIGN_LINESMOOTH);
		stream->write(lineSmooth);
	}
	{
		bool polySmooth = shape->polySmooth();
		AutoChunk chunk(this, SIGN_POLYGONSMOOTH);
		stream->write(polySmooth);
	}
	{
		float lineWidth = shape->lineWidth();
		AutoChunk chunk(this, SIGN_LINEWIDTH);
		stream->write(lineWidth);
	}
	{
		float pointSize = shape->pointSize();
		AutoChunk chunk(this, SIGN_POINTSIZE);
		stream->write(pointSize);
	}
	{
		char polyMode = (char)shape->polyMode();
		AutoChunk chunk(this, SIGN_POLYGONMODE);
		stream->write(polyMode);
	}
	{
		bool transparent = shape->transparent();
		AutoChunk chunk(this, SIGN_TRANSPARENT);
		stream->write(transparent);
	}
	{
		bool normalize = shape->normalize();
		AutoChunk chunk(this, SIGN_NORMALIZE);
		stream->write(normalize);
	}
	{
		AutoChunk chunk(this, SIGN_MATRIX);
		stream->write(shape->matrix());
	}
	{
		AutoChunk chunk(this, SIGN_COLOR);
		stream->write(shape->color());
	}
	if (BMaterial* material = shape->material())
	{
		write(material);
	}
	if (BTexture* texture = shape->texture())
	{
		write(texture);
	}
	if (BProgram* program = shape->program())
	{
		write(program);
	}
	if (BShape* proxy = shape->proxy())
	{
		AutoChunk chunk(this, SIGN_PROXY);
		write(proxy);
	}
	return true;
}
bool member_BObcDocument::writeMesh(const BMesh* mesh)
{
	{
		AutoChunk chunk(this, SIGN_OPTIMIZED);
		stream->write(mesh->optimized());
	}
	if (const BVectorArray* vertices = mesh->vertices())
	{
		AutoChunk chunk(this, SIGN_VERTICES);
		stream->write(vertices->size());
		stream->write(vertices->data(), vertices->size());
	}
	if (const BVectorArray* normals = mesh->normals())
	{
		AutoChunk chunk(this, SIGN_NORMALS);
		stream->write(normals->size());
		stream->write(normals->data(), normals->size());
	}
	if (const BColorArray* colors = mesh->colors())
	{
		AutoChunk chunk(this, SIGN_COLORS);
		stream->write(colors->size());
		stream->write(colors->data(), colors->size());
	}
	if (const BCoordArray* texCoords = mesh->texCoords())
	{
		AutoChunk chunk(this, SIGN_TEXCOORDS);
		stream->write(texCoords->size());
		stream->write(texCoords->data(), texCoords->size());
	}
	if (const BFaceArray* faces = mesh->faces())
	{
		AutoChunk chunk(this, SIGN_FACES);
		stream->write(faces->size());
		stream->write(faces->data(), faces->size());
	}
	return true;
}
bool member_BObcDocument::writeGeometry(const BGeometry* geometry)
{
	{
		AutoChunk chunk(this, SIGN_OPTIMIZED);
		bool optimized = geometry->optimized();
		stream->write(optimized);
	}
	if (const BVectorArray* vertices = geometry->vertices())
	{
		AutoChunk chunk(this, SIGN_VERTICES);
		stream->write(vertices->size());
		stream->write(vertices->data(), vertices->size());
	}
	if (const BVectorArray* normals = geometry->normals())
	{
		AutoChunk chunk(this, SIGN_NORMALS);
		stream->write(normals->size());
		stream->write(normals->data(), normals->size());
	}
	if (const BColorArray* colors = geometry->colors())
	{
		AutoChunk chunk(this, SIGN_COLORS);
		stream->write(colors->size());
		stream->write(colors->data(), colors->size());
	}
	if (const BCoordArray* texCoords = geometry->texCoords())
	{
		AutoChunk chunk(this, SIGN_TEXCOORDS);
		stream->write(texCoords->size());
		stream->write(texCoords->data(), texCoords->size());
	}
	for (int i = 0; i < geometry->elementCount(); i++)
	{
		const BElement* element = geometry->element(i);
		write(element);
	}
	return true;
}
bool member_BObcDocument::writeElement(const BElement* element)
{
	{
		AutoChunk chunk(this, SIGN_VISIBLE);
		bool visible = element->visible();
		stream->write(visible);
	}
	{
		AutoChunk chunk(this, SIGN_PRIMITIVE);
		int primitive = element->primitive();
		stream->write(primitive);
	}
	{
		AutoChunk chunk(this, SIGN_FIRST);
		int first = element->first();
		stream->write(first);
	}
	{
		AutoChunk chunk(this, SIGN_COUNT);
		int count = element->count();
		stream->write(count);
	}
	const BIntArray* indices = element->indices();
	if (indices)
	{
		AutoChunk chunk(this, SIGN_INDICES);
		stream->write(indices->size());
		stream->write(indices->data(), indices->size());
	}
	const BPieceArray* pieces = element->pieces();
	if (pieces)
	{
		AutoChunk chunk(this, SIGN_PIECES);
		stream->write(pieces->size());
		stream->write(pieces->data(), pieces->size());
	}
	return true;
}
bool member_BObcDocument::writeTextual(const BTextual* textual)
{
	{
		AutoChunk chunk(this, SIGN_QUAD);
		const BQuad& quad = textual->quad();
		stream->write(quad);
	}
	{
		AutoChunk chunk(this, SIGN_ALIGN);
		Align align = textual->align();
		stream->write(align);
	}
	if (const BFont* font = textual->font())
	{
		AutoChunk chunk(this, SIGN_FONT);
		stream->write(font->family());
		stream->write(font->size());
	}
	{
		AutoChunk chunk(this, SIGN_GLYPSIZE);
		BReal glyphSize = textual->glyphSize();
		stream->write(glyphSize);
	}
	if(textual->text().size())
	{
		AutoChunk chunk(this, SIGN_TEXT);
		stream->write(textual->text());
	}
	if (const BColorArray* colors = textual->colors())
	{
		AutoChunk chunk(this, SIGN_COLORS);
		stream->write(colors->size());
		stream->write(colors->data(), colors->size());
	}
	return true;
}
bool member_BObcDocument::writeBillboard(const BBillboard* billboard)
{
	const BQuad& quad = billboard->quad();
	{
		AutoChunk chunk(this, SIGN_QUAD);
		stream->write(quad);
	}
	const BVector& axis = billboard->axis();
	{
		AutoChunk chunk(this, SIGN_AXIS);
		stream->write(axis);
	}
	return true;
}
bool member_BObcDocument::writeParticle(const BParticle* particle)
{
	return false;
}

bool member_BObcDocument::writeCube(const BCube* cube)
{
	{
		AutoChunk chunk(this, SIGN_LENGTH);
		BReal length = cube->length();
		stream->write(length);
	}
	{
		AutoChunk chunk(this, SIGN_WIDTH);
		BReal width = cube->width();
		stream->write(width);
	}
	{
		AutoChunk chunk(this, SIGN_HEIGHT);
		BReal height = cube->height();
		stream->write(height);
	}
	{
		AutoChunk chunk(this, SIGN_LENGTHSEGMENTS);
		int lengthSegments = cube->lengthSegments();
		stream->write(lengthSegments);
	}
	{
		AutoChunk chunk(this, SIGN_WIDTHSEGMENT);
		int widthSegments = cube->widthSegments();
		stream->write(widthSegments);
	}
	{
		AutoChunk chunk(this, SIGN_HEIGHTSEGMENT);
		int heightSegments = cube->heightSegments();
		stream->write(heightSegments);
	}
	return true;
}
bool member_BObcDocument::writeCone(const BCone* cone)
{
	{
		AutoChunk chunk(this, SIGN_RADIUS);
		BReal radius = cone->radius();
		stream->write(radius);
	}
	{
		AutoChunk chunk(this, SIGN_HEIGHT);
		BReal height = cone->height();
		stream->write(height);
	}
	{
		AutoChunk chunk(this, SIGN_SIDES);
		int sides = cone->sides();
		stream->write(sides);
	}
	{
		AutoChunk chunk(this, SIGN_SEGMENTS);
		int segments = cone->segments();
		stream->write(segments);
	}
	{
		AutoChunk chunk(this, SIGN_RADIUSSEGMENTS);
		int radiusSegments = cone->radiusSegments();
		stream->write(radiusSegments);
	}
	return true;
}
bool member_BObcDocument::writeCylinder(const BCylinder* cylinder)
{
	{
		AutoChunk chunk(this, SIGN_RADIUS);
		BReal radius = cylinder->radius();
		stream->write(radius);
	}
	{
		AutoChunk chunk(this, SIGN_HEIGHT);
		BReal height = cylinder->height();
		stream->write(height);
	}
	{
		AutoChunk chunk(this, SIGN_SIDES);
		int sides = cylinder->sides();
		stream->write(sides);
	}
	{
		AutoChunk chunk(this, SIGN_HEIGHTSEGMENT);
		int heightSegments = cylinder->heightSegments();
		stream->write(heightSegments);
	}
	{
		AutoChunk chunk(this, SIGN_RADIUSSEGMENTS);
		int radiusSegments = cylinder->radiusSegments();
		stream->write(radiusSegments);
	}
	return true;
}
bool member_BObcDocument::writeSphere(const BSphere* sphere)
{
	{
		AutoChunk chunk(this, SIGN_RADIUS);
		BReal radius = sphere->radius();
		stream->write(radius);
	}
	{
		AutoChunk chunk(this, SIGN_SIDES);
		int sides = sphere->sides();
		stream->write(sides);
	}
	{
		AutoChunk chunk(this, SIGN_SEGMENTS);
		int segments = sphere->segments();
		stream->write(segments);
	}
	return true;
}
bool member_BObcDocument::writeGeoSphere(const BGeoSphere* geoSphere)
{
	{
		AutoChunk chunk(this, SIGN_RADIUS);
		BReal radius = geoSphere->radius();
		stream->write(radius);
	}
	{
		AutoChunk chunk(this, SIGN_SEGMENTS);
		int segments = geoSphere->divide();
		stream->write(segments);
	}
	return true;
}
bool member_BObcDocument::writeTube(const BTube* tube)
{
	{
		AutoChunk chunk(this, SIGN_RADIUS);
		BReal radius = tube->radius();
		stream->write(radius);
	}
	{
		AutoChunk chunk(this, SIGN_HEIGHT);
		BReal height = tube->height();
		stream->write(height);
	}
	{
		AutoChunk chunk(this, SIGN_SIDES);
		int sides = tube->sides();
		stream->write(sides);
	}
	{
		AutoChunk chunk(this, SIGN_HEIGHTSEGMENT);
		int heightSegments = tube->heightSegments();
		stream->write(heightSegments);
	}
	{
		AutoChunk chunk(this, SIGN_RADIUSSEGMENTS);
		int radiusSegments = tube->radiusSegments();
		stream->write(radiusSegments);
	}
	{
		AutoChunk chunk(this, SIGN_THICKNESS);
		BReal thickness = tube->thickness();
		stream->write(thickness);
	}
	return true;
}
bool member_BObcDocument::writeTorus(const BTorus* torus)
{
	{
		AutoChunk chunk(this, SIGN_RADIUS);
		BReal radius = torus->radius();
		stream->write(radius);
	}
	{
		AutoChunk chunk(this, SIGN_OUTERRADIUS);
		BReal outerRadius = torus->outerRadius();
		stream->write(outerRadius);
	}
	{
		AutoChunk chunk(this, SIGN_SIDES);
		int sides = torus->sides();
		stream->write(sides);
	}
	{
		AutoChunk chunk(this, SIGN_SEGMENTS);
		int segments = torus->segments();
		stream->write(segments);
	}
	return true;
}
bool member_BObcDocument::writeSurface(const BSurface* surface)
{
	{
		AutoChunk chunk(this, SIGN_QUAD);
		BQuad quad = surface->quadEdges();
		stream->write(quad);
	}
	{
		AutoChunk chunk(this, SIGN_HORSEGMENT);
		int horSegment = surface->horizontalSegment();
		stream->write(horSegment);
	}
	{
		AutoChunk chunk(this, SIGN_VERSEGMENT);
		int verSegment = surface->verticalSegment();
		stream->write(verSegment);
	}
	return true;
}
bool member_BObcDocument::writeTerrain(const BTerrain* terrain)
{
	{
		AutoChunk chunk(this, SIGN_ALIGN);
		Align align = terrain->align();
		stream->write(align);
	}
	{
		AutoChunk chunk(this, SIGN_WIDTH);
		BReal width = terrain->width();
		stream->write(width);
	}
	{
		AutoChunk chunk(this, SIGN_HEIGHT);
		BReal height = terrain->height();
		stream->write(height);
	}
	const BRealTable& elevation = terrain->elevation();
	if (elevation.size())
	{
		AutoChunk chunk(this, SIGN_ELEVATION);
		stream->write(elevation.row());
		stream->write(elevation.column());
		stream->write(elevation.data(), elevation.size());
	}
	return true;
}
bool member_BObcDocument::writeCapsule(const BCapsule* capsule)
{
	{
		AutoChunk chunk(this, SIGN_RADIUS);
		BReal radius = capsule->radius();
		stream->write(radius);
	}
	{
		AutoChunk chunk(this, SIGN_HEIGHT);
		BReal height = capsule->height();
		stream->write(height);
	}
	{
		AutoChunk chunk(this, SIGN_SIDES);
		int sides = capsule->sides();
		stream->write(sides);
	}
	{
		AutoChunk chunk(this, SIGN_HEIGHTSEGMENT);
		int heightSegments = capsule->heightSegments();
		stream->write(heightSegments);
	}
	{
		AutoChunk chunk(this, SIGN_RADIUSSEGMENTS);
		int radiusSegments = capsule->radiusSegments();
		stream->write(radiusSegments);
	}
	return true;
}
bool member_BObcDocument::writeLineStripe(const BLineStripe* lineStripe)
{
	const BVectorArray* vertices = lineStripe->vertices();
	if (vertices && vertices->size())
	{
		AutoChunk chunk(this, SIGN_VERTICES);
		stream->write(vertices->size());
		stream->write(vertices->data(), vertices->size());

	}

	{
		AutoChunk chunk(this, SIGN_RADIUS);
		BReal radius = lineStripe->radius();
		stream->write(radius);
	}

	if (vertices && vertices->size())
	{
		AutoChunk chunk(this, SIGN_RADIUSES);
		stream->write(vertices->size());
		for (int i = 0; i < vertices->size(); i++)
		{
			BReal radius = lineStripe->radius(i);
			stream->write(radius);
		}
	}

	{
		AutoChunk chunk(this, SIGN_CLOSELOOP);
		bool closeLoop = lineStripe->closeLoop();
		stream->write(closeLoop);
	}

	{
		AutoChunk chunk(this, SIGN_THICKNESS);
		BReal thickness = lineStripe->thickness();
		stream->write(thickness);
	}

	return true;
}
bool member_BObcDocument::writeSplineCurve(const BSplineCurve* splineCurve)
{
	const BVectorArray* vertices = splineCurve->vertices();
	if (vertices && vertices->size())
	{
		AutoChunk chunk(this, SIGN_VERTICES);
		stream->write(vertices->size());
		stream->write(vertices->data(), vertices->size());
	}

	{
		AutoChunk chunk(this, SIGN_CLOSELOOP);
		stream->write(splineCurve->closeLoop());
	}

	{
		AutoChunk chunk(this, SIGN_THICKNESS);
		stream->write(splineCurve->thickness());
	}

	return true;
}

bool member_BObcDocument::writeMaterial(const BMaterial* material)
{
	{
		AutoChunk chunk(this, SIGN_AMBIENT);
		BColor ambient = material->ambient();
		stream->write(ambient);
	}
	{
		AutoChunk chunk(this, SIGN_DIFFUSE);
		BColor diffuse = material->diffuse();
		stream->write(diffuse);
	}
	{
		AutoChunk chunk(this, SIGN_SPECULAR);
		BColor specular = material->specular();
		stream->write(specular);
	}
	{
		AutoChunk chunk(this, SIGN_EMISSION);
		BColor emission = material->emission();
		stream->write(emission);
	}
	{
		AutoChunk chunk(this, SIGN_SHININESS);
		float shininess = material->shininess();
		stream->write(shininess);
	}
	return true;
}
bool member_BObcDocument::writeTexture(const BTexture* texture)
{
	{
		AutoChunk chunk(this, SIGN_BLEND);
		int blend = texture->blend();
		stream->write(blend);
	}
	{
		AutoChunk chunk(this, SIGN_BLENDCOLOR);
		BColor color = texture->blendColor();
		stream->write(color);
	}
	{
		AutoChunk chunk(this, SIGN_FILTER);
		int filter = texture->filter();
		stream->write(filter);
	}
	{
		AutoChunk chunk(this, SIGN_WRAP);
		int wrap = texture->wrap();
		stream->write(wrap);
	}
	{
		AutoChunk chunk(this, SIGN_MIPMAP);
		bool mipmap = texture->mipmap();
		stream->write(mipmap);
	}
	return true;
}
bool member_BObcDocument::writeImage(const BImage* image)
{
	const BString& fileName = image->fileName();
	if (fileName.size())
	{
		AutoChunk chunk(this, SIGN_FILENAME);
		stream->write(fileName);
		if (BFile::Exist(fileName))
			return true;
		BReadWrite* rw = GetReadWrite(fileName.ext());
		if (!rw)
			rw = GetReadWrite(fileName.name());
		if (rw)
		{
			BBuffer buffer;
			rw->write(buffer, image);
			stream->write(buffer.bytes());
		}
		return true;
	}
	else
	{
		{
			AutoChunk chunk(this, SIGN_FORMAT);
			int format = image->format();
			stream->write(format);
		}
		{
			AutoChunk chunk(this, SIGN_SIZE);
			BSize size = image->size();
			stream->write(size);
		}
		const BByteArray* pixels = image->pixels();
		if (pixels)
		{
			AutoChunk chunk(this, SIGN_PIXELS);
			stream->write(pixels->size());
			stream->write(pixels->data(), pixels->size());
		}
	}
	return true;
}
bool member_BObcDocument::writePixmap(const BPixmap* pixmap)
{
	{
		AutoChunk chunk(this, SIGN_SIZE);
		BSize size = pixmap->size();
		stream->write(size);
	}
	return true;
}
bool member_BObcDocument::writeProgram(const BProgram* program)
{
	for (int i = 0; i < program->shaderCount(); i++)
	{
		const BShader* shader = program->shader(i);
		writeShader(shader);
	}
	for (int i = 0; i < program->uniformCount(); i++)
	{
		const BUniform* uniform = program->uniform(i);
		writeUniform(uniform);
	}
	return true;
}
bool member_BObcDocument::writeShader(const BShader* shader)
{
	{
		AutoChunk chunk(this, SIGN_TYPE);
		int type = shader->type();
		stream->write(type);
	}
	if(shader->text().size())
	{
		AutoChunk chunk(this, SIGN_TEXT);
		stream->write(shader->text());
	}
	return true;
}
bool member_BObcDocument::writeUniform(const BUniform* uniform)
{
	{
		AutoChunk chunk(this, SIGN_TYPE);
		int type = uniform->type();
		stream->write(type);
	}
	{
		AutoChunk chunk(this, SIGN_SIZE);
		int size = uniform->size();
		stream->write(size);
	}
	return true;
}
bool member_BObcDocument::writeScript(const BScript* script)
{
	const BString& path = script->path();
	if (path.size())
	{
		AutoChunk chunk(this, SIGN_PATH);
		stream->write(path);
	}

	if (int count = script->sourceCount())
	{
		for (int i = 0; i < count; i++)
		{
			write(script->source(i));
		}
	}

	if (int count = script->breakpointCount())
	{
		AutoChunk chunk(this, SIGN_BREAKPOINTS);
		stream->write(count);
		for (int i = 0; i < count; i++)
		{
			stream->write(script->breakpoint(i));
		}
	}

	const BExpHolderArray& sequence = script->sequence();
	if (int size = sequence.size())
	{
		AutoChunk chunk(this, SIGN_SEQUENCE);
		stream->write(size);
		for (int i = 0; i < sequence.size(); i++)
		{
			AutoChunk chunk(this, SIGN_EXP);
			writeExp(sequence[i]);
		}
	}
	return true;
}
bool member_BObcDocument::writeSource(const BSource* source)
{
	if (source->fileName().size())
	{
		AutoChunk chunk(this, SIGN_FILENAME);
		stream->write(source->fileName());
	}
	if (source->text().size())
	{
		AutoChunk chunk(this, SIGN_TEXT);
		stream->write(source->text());
	}
	return true;
}
bool member_BObcDocument::writeExp(const BExp* exp)
{
	{
		AutoChunk chunk(this, SIGN_SYNTAX);
		stream->write(exp->syntax);
	}
	if (exp->info.size())
	{
		AutoChunk chunk(this, SIGN_INFORMATION);
		stream->write(exp->info);
	}
	if (exp->type.size())
	{
		AutoChunk chunk(this, SIGN_TYPE);
		stream->write(exp->type);
	}
	if (exp->name.size())
	{
		AutoChunk chunk(this, SIGN_NAME);
		stream->write(exp->name);
	}
	if (exp->value.valid())
	{
		AutoChunk chunk(this, SIGN_VALUE);
		stream->write(exp->type);
		if (exp->type == "bool")
			stream->write((bool)exp->value);
		else if (exp->type == "char")
			stream->write((char)exp->value);
		else if (exp->type == "short")
			stream->write((short)exp->value);
		else if (exp->type == "int")
			stream->write((int)exp->value);
		else if (exp->type == "long")
			stream->write((long long)exp->value);
		else if (exp->type == "float")
			stream->write((float)exp->value);
		else if (exp->type == "double")
			stream->write((double)exp->value);
		else if (exp->type == "string")
			stream->write((const BString&)exp->value);
	}
	if (int size = exp->params.size())
	{
		for (int i = 0; i < size; i++)
		{
			AutoChunk chunk(this, SIGN_EXP);
			writeExp(exp->params[i]);
		}
	}
	return true;
}

bool member_BObcDocument::writeSonNode(const BSonNode* sonNode)
{
	if (sonNode->format().size())
	{
		AutoChunk chunk(this, SIGN_FORMAT);
		stream->write(sonNode->format());
	}

	if (sonNode->text().size())
	{
		AutoChunk chunk(this, SIGN_TEXT);
		stream->write(sonNode->text());
	}

	const BMap<BString, BString>& attribMap = sonNode->attribMap();
	if (attribMap.size())
	{
		for (auto it = attribMap.begin(); it.valid(); ++it)
		{
			AutoChunk chunk(this, SIGN_ATTRIB);
			stream->write(it.key());
			stream->write(it.value());
		}
	}

	for (int i = 0; i < sonNode->childCount(); i++)
	{
		this->write(sonNode->child(i));
	}

	return true;
}
bool member_BObcDocument::writeXmlNode(const BXmlNode* xmlNode)
{
	if (xmlNode->format().size())
	{
		AutoChunk chunk(this, SIGN_FORMAT);
		stream->write(xmlNode->format());
	}
	if (xmlNode->text().size())
	{
		AutoChunk chunk(this, SIGN_TEXT);
		stream->write(xmlNode->text());
	}
	const BMap<BString, BString>& attribMap = xmlNode->attribMap();
	if (attribMap.size())
	{
		for (auto it = attribMap.begin(); it.valid(); ++it)
		{
			AutoChunk chunk(this, SIGN_ATTRIB);
			stream->write(it.key());
			stream->write(it.value());
		}
	}
	for (int i = 0; i < xmlNode->childCount(); i++)
	{
		this->write(xmlNode->child(i));
	}

	return true;
}

